If one is working with a database, a Null* type is useful for most scenarios as one typically does not want a "zero" value going through, you want the NOT NULL constraints etc. to kick up and remind you that you haven't passed in all the data necessary.
So you create a structure like the following:
type Role struct {
    Id   sql.NullInt64
    Code sql.NullString
}
Thats great, but now you cannot get direct access to the properties and have to use Role.Id.Value to both get and set, this is going to  get pretty old in a large app when you have to have the extra step every single time you want access to the properties.
It would be nice if you could assign directly eg. Role.Code = "Fsfs", and be able to do something like Role.Code.IsNull when you are interested in null checking. Is such a thing possible?
Is using intermediate pointer value(s) an option?
package main
import "fmt"
type tmp struct {
    Value int
}
func getInt() *int {
    i := 123
    return &i
}
func main() {
    // Re
    var v *int
    v = nil
    fmt.Printf("%T / %v\n", v, v)
    if v == nil {
        println("nil...")
    }
    v = getInt()
    fmt.Printf("%T / %v\n", v, *v)
    if v != nil {
        println("not nil...")
    }
    s := tmp{*v}
    fmt.Printf("%T / %v\n", s, s)
}
http://play.golang.org/p/lBrwTKh6-v
You can access Role.Code like that:
var r *Role
r.Code = *code
You can check for null like this:
fmt.Println(r.Code, r.Code.Valid)
If you change the value of r.Code manually without using an sql.Scanner a Setter could be helpful:
func (r *Role) SetCode(code string) {
  r.Code.String = code
  r.Code.Valid = true
}
func main() {
var r *Role 
r.SetCode("mi")
if r.Code.Valid {
  fmt.Println(r.Code)
}
I tried this out here: https://play.golang.org/p/faxQUm-2lr
Keep app and database code separate.
// Role belongs to app code, no compromises.
type Role struct {
    Id int64
    Code string
}
Model the database.
// Database has tables with columns.  
type Table struct {
    Name string
    Columns []string
}
var RoleTable = Table{
    Name: "roles",
    Columns: []string{
        "id",
        "code",
    },
}
Write code once to convert between model and database row.
// Database package needs to make it work.
// Write a model to database row. 
type Writer struct {
    Role
}
func (w *Writer) Write() []interface{} {
    return []interface{}{
        w.Role.Id,
        sql.NullString{
            Valid: len(w.Role.Code) > 0,
            String: w.Role.String,
        },
    }
}
// Read a database row into model. 
type Reader struct {
    Id int64
    Code sql.NullString
}
func (r *Reader) Scan(row *sql.Row) error {
    return row.Scan(
        &r.Id,
        &r.Code,
    )
}
func (r *Reader) Read() Role {
    return Role{
        Id: r.Id,
        Code: r.Code.String,
    }
}
Your schema is decoupled from app model. You can flatten structures like user contact details when saving or loading.
// Nested struct in app code. 
type User struct {
    TwitterProfile struct {
        Id string
        ScreenName string
    }
}
// Database row is normalized flat. 
var UserTable = Table{
    Name: "users",
    Columns: []string{
        "twitter_id",
        "twitter_screen_name",
    },
}
It's flexible. You can even scan join rows without intermediate structs.
type RowMux struct {
    vs []interface{}
}
func (mux *RowMux) Scan(vs ...interface{}) error {
    mux.vs = append(mux.vs, vs...)
    return nil
}
func (mux *RowMux) Mux(row *sql.Row) error {
    return row.Scan(mux.vs...)
}
// Scan join rows!
row := db.QueryRow(`
    SELECT users.*, roles.*
    FROM users
    JOIN roles ON users.id = roles.user_id
    WHERE users.twitter_id = "123"
`)
mux := &RowMux{}
userReader := &UserReader{}
userReader.Scan(mux)
roleReader := &RoleReader{}
roleReader.Scan(mux)
if err := mux.Mux(row); err != nil {
    panic(err)
}
user := userReader.Read()
role := roleReader.Read()
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With