If you have dealt with SQL in Golang, you know that handling NULL values didn’t come easily with it. The database/sql
interface already support NULL values by usage of Go’s nil
, but the design of the language doesn’t permit to assign nil
to a string
or int
variable. In this post, I will show you the ways.
1) Pointers
In Go, if the primitive variable isn’t a pointer, you can’t assign nil
. Pointers are usually using for passing the shared data to another function to make memory usage more efficient, but we have also another good reason to use this; handling NULL values.
type User struct {
Id int64
Name *string
Age *int32
}
err := db.QueryRow("SELECT NULL, 2").Scan(&u.Name, &u.Age)
In this case, we can set Name
field as nil
of its pointer. The sql.Scan()
handling NULL values by set the given pointer arguments as nil
. json.Marshall()
operations are also supported to set nil
pointers as null
in JSON format. But every usage of the variables or the struct fields that are pointers, you have to check are these nil
or not. If u.Age
is a nil
, then you do dereference it, the program will be crashed.
2) sql.Null*
There are a few structs defined in the sql
package. It’s allow to use variables in different primitive types that can be nullable. These structs are also implements a scanner and a value interface to allow to use in sql
operations. But it doesn’t handle JSON marshalling by default, so you have to implement your own. Documentation
type User struct {
Id int64
Name sql.NullString
Age sql.NullInt32
}
err := db.QueryRow("SELECT 'Ekin', NULL").Scan(&u.Name, &u.Age)
For example, we looking at sql.NullString
struct that has two fields that are String
and Valid
. For the non-NULL values, u.Name.Valid
field will equal to true
and u.Name.String
equal to "Ekin"
. Otherwise, u.Name.Valid
will be false
and u.Name.String
will be ""
. If your field type is NullString
, first you have to check is the string valid or not. If is valid, we can obtain value by the u.Name.String
field.
3) github.com/guregu/null
This is the third way, an external package from Github for the handle NULL values and very similar to second way. But it’s more easier to create nullable types. It’s also support JSON marshall operations. Documentation
4) Use COALESCE function
COALESCE is the SQL function in the most of relational database systems (SQLite, PostgreSQL, MySQL, SQL Server, and Oracle). This function does try to return first non-NULL value according to its given arguments. Documentation
type User struct {
Id int64
Name string
Age int32
}
err := db.QueryRow("SELECT COALESCE(NULL, '')").Scan(&u.Name)
5) Don’t use NULL values
Yes, this isn’t a programmatical solution but we can avoid NULL returns from queries by not using NULL values. Usually NULL values come from the default value of the column, or we set values as NULL. So, if we not use NULL values, we don’t need to handle it. 😎
But it doesn’t means that we shouldn’t use NULL. It’s sometimes can be necessary sometimes not. I suggest you decide it by yourself.