
在 Go 操作 MySQL 时,需将 Go 的空字符串("")显式映射为 SQL 的 NULL,而非默认插入空字符串;核心方法是使用 sql.NullString 并配合自定义封装函数实现安全、可读的空值处理。
在 go 操作 mysql 时,需将 go 的空字符串(`""`)显式映射为 sql 的 `null`,而非默认插入空字符串;核心方法是使用 `sql.nullstring` 并配合自定义封装函数实现安全、可读的空值处理。
Go 标准库中的 database/sql 提供了 sql.NullString 类型,它是一个结构体,包含 String string 和 Valid bool 两个字段:仅当 Valid 为 true 时,该值才会作为非 NULL 字符串写入数据库;若 Valid 为 false,则底层驱动会将其序列化为 SQL NULL。
为简化使用,推荐封装一个辅助函数:
import "database/sql"
func NewNullString(s string) sql.NullString {
if s == "" {
return sql.NullString{} // Valid=false, String="" → 插入为 NULL
}
return sql.NullString{
String: s,
Valid: true, // 显式标记有效,确保插入实际字符串
}
}
然后,在你的 Exec 调用中,将可能为空的字段(如 ve.EventInfo、ve.UrlPath、ve.Domain)统一包裹:
_, err := m.Db.Exec(`INSERT INTO
visitor_events
(type,
info,
url_path,
visitor_id,
created_at,
domain)
VALUES (?, ?, ?, ?, ?, ?)`,
m.SaveEventType(ve),
NewNullString(ve.EventInfo), // ✅ 空字符串 → NULL
NewNullString(m.SaveURLPath(ve.UrlPath)), // ✅ 同理处理
ve.VisitorId,
time.Now().UTC(),
NewNullString(ve.Domain), // ✅ 统一语义
)
if err != nil {
// handle error
}
⚠️ 注意事项:
- 不要直接传
sql.NullString{}(未设置Valid=true)以外的零值,否则所有字段都会变成NULL; -
sql.NullString仅适用于STRING/TEXT类型字段;其他类型(如INT、TIME)需分别使用sql.NullInt64、sql.NullTime等对应类型; - 若字段在数据库中定义为
NOT NULL,插入NULL将触发 SQL 错误,请确保表结构允许NULL; - 使用
NewNullString后,后续查询该字段也需用sql.NullString接收,否则Scan会报错。
✅ 总结:通过封装 NewNullString 函数,你能在业务逻辑层清晰表达“空字符串即无值”的语义,既避免手动判断分散代码,又确保数据库写入符合预期,是 Go + SQL 开发中的推荐实践。











