I'm using gorm
to define my db table schema. Noticed that gorm
itself uses time.Time
for created_at
and *time.Time
for deleted_at
. I'm assuming this is because deleted_at
has cases of being NULL
.
I also noticed that for many Golang ORMs they use sql.NullFloat64
for storing db values that could be a float64
or NULL
. Why not just use *float64
instead of sql.NullFloat64
? What's the difference?
type Geo struct {
latitude *float64
longitude sql.NullFloat64
}
// What is the difference between latitude and longitude in this case?
From Russ Cox (biggest Go's contributor according to Github) : https://groups.google.com/forum/#!topic/golang-nuts/vOTFu2SMNeA
There's no effective difference. We thought people might want to use NullString because it is so common and perhaps expresses the intent more clearly than *string. But either will work.
I'm thinking though that using a pointer might give the GC one more thing to track. It probably depends on the usage.
On some very simple code, using -gcflags=-m
to build, the escape analysis does say that new(float64) escapes to heap
(here is the dummy code I used: https://play.golang.org/p/K4sQaXyQKG).
Also, when debugging, printing a struct containing a sql.NullSomething
({value:{Float64:1 Valid:true}}
) looks better than a struct containing a pointer ({value:0xc82000a420}
).
So I'd recommend the usage of the sql.Null*
structs.