从 Go 中的 sql 获取 nil 值

khu*_*bui 1 mysql go query-builder

假设我有一个struct Profile和sql 表profiles

type Profile struct {
    ID        int       `json:"id"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
    FirstName string    `json:"first_name"`
    LastName  string    `json:"last_name"`
    Age       int       `json:"age"`
}
Run Code Online (Sandbox Code Playgroud)

并且,我从配置文件表中获取一条记录,分配到配置文件结构中。

这些字段允许 null,因此我在分配给结构之前使用sql.NullStringsql.NullInt64pq.NullTime检查有效值。

// ... DB.Query(...)
// ... rows.Next()
// ... rows.Scan()
// ...
if firstName.Valid {
    p.FirstName = firstName.String
}
if lastName.Valid {
    p.LastName = lastName.String
}
if age.Valid {
    p.Age = age.Int64
}
// ...
Run Code Online (Sandbox Code Playgroud)

如果我有超过 10 个表,每个表有超过 30 列,我必须一次又一次地检查所有变量。这使得代码变得丑陋,有人有什么建议让它变得漂亮吗?

Fli*_*mzy 5

你根本不应该这样检查。可空类型旨在直接在结构中使用:

type Profile struct {
    ID        sql.NullInt64  `json:"id"`
    CreatedAt time.Time      `json:"created_at"`
    UpdatedAt time.Time      `json:"updated_at"`
    FirstName sql.NullString `json:"first_name"`
    LastName  sql.NullString `json:"last_name"`
    Age       sql.NullInt64  `json:"age"`
}
Run Code Online (Sandbox Code Playgroud)

然后使用例如 访问这些值product.FirstName.String()。没有理由进行检查product.FirstName.Valid,除非您真正关心和空值之间的区别nil(在您问题的示例中,您显然不关心这种区别)。

在某些情况下可能更合适的另一种选择是仅使用指针:

type Profile struct {
    ID        *int      `json:"id"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
    FirstName *string   `json:"first_name"`
    LastName  *string   `json:"last_name"`
    Age       *int      `json:"age"`
}
Run Code Online (Sandbox Code Playgroud)

当然,任何使用这些变量的代码都必须取消引用它们,并检查nil,因此这可能并不总是最理想的,具体取决于您如何使用这些值。

NULL如果您从不关心值和空值之间的区别,第三种选择是创建您自己的类型,将它们视为相同的。例子:

type myString string

func (s *myString) Scan(src interface{}) error {
    if src == nil {
        return nil
    }
    if value, ok := src.(string); ok {
        *s = value
        return nil
    }
    return fmt.Errorf("Unsupported type for myString: %T", src)
}
Run Code Online (Sandbox Code Playgroud)