Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qwerty2501/8839af87946571943a6c4f623c6124e2 to your computer and use it in GitHub Desktop.
Save qwerty2501/8839af87946571943a6c4f623c6124e2 to your computer and use it in GitHub Desktop.

A problem runtime error due to lack of Generics

Introduction

This document is written my experience and thinking about Go.
Go is simple. And it is good that performance in runtime. But in Go I had to write code that is unsafe in some cases.I think that it is caused by lack of Generics.
I will write about them.

Case of json.Unmarshal

I was writing a common code with json.Unmarshal.
It’s written as follows.

jsonText := `
{
    "foo":"bar"
}
`
var fooBar FooBar

//error in runtime
//json: Unmarshal(non-pointer main.FooBar)foo:
if err := json.Unmarshal([]byte(jsonText), fooBar); err != nil {
    fmt.Printf(err.Error())
}

//output is "foo:"
fmt.Println("foo:" + fooBar.Foo)

This code is wrong. The json.Unmarshal's result is error. Because the argument of fooBar is not pointer.
The correct code as follows.  

jsonText := `
{
    "foo":"bar"
}
`
var fooBar FooBar

//err is nil
//Because argument of fooBar is pointer.
if err := json.Unmarshal([]byte(jsonText), &fooBar); err != nil {
    fmt.Printf(err.Error())
}

//output is "foo:bar"
fmt.Println("foo:" + fooBar.Foo)

Case of gorm

I got another error when I was writing code with gorm at work.
I refrain from writing detailed code due from company intention.
Describing only the necessary parts as follows.

type FooBar struct {
	Foo string
}

type FooBar2 struct {
	ID  uint
	Foo string
}

func main() {
	db, _ := gorm.Open("mysql", dbArgs)
	db.Create(&FooBar{Foo: "test1"}) //Succeed
	db.Create(FooBar{Foo: "test2"})  //Succeed
	db.Create(&FooBar2{Foo: "test3"})//Succeed
    db.Create(FooBar2{Foo: "test4"}) //An error will occur (using unaddressable value)
    
    /*
        It seems to struct with numeric ID will be auto incriment and primary key by default in gorm.
        So, the FooBar2's variable should be written ID from gorm and addressable.
    */
}

Then, I wrote code at work as follows.

if /* Rarely become true */ {
    db.Create(FooBar2{Foo: "test4"})
}

This code is Later there will be serious runtime probrems. This only has to write a test code and take countermeasures. But The majority of other statically typed language make such code a compile error with Generics.

Conclusion

  • These problem can be compile error. but An runtime error occur in go.
  • Need type constraint (eg: Generics, or other type system.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment