英文:
How to detect a zeroed value of struct safely in Go?
问题
我尝试为MySQL编写了一个简单的ORM,遇到了一个问题:如果一个定义的结构体缺少某些字段:
type User struct {
ID int64
Username string
Password string
Email string
Comment string
}
var u = User{Username: "user_0001", Password: "password"}
User的某些字段没有给定值,那么它们的值将是零值,比如字符串""
,布尔值false
,整数0
等。
因此,我使用reflect
来获取字段名和值,生成一个插入行的SQL语句。
INSERT INTO User (Id, Username, Password, Email, Comment) Values (0, "user_0001", "password", , ,)
你可以看到字符串中有一些零值,如果我检测到空字符串""
并跳过它们,可能会跳过正常的值。
英文:
I tried to written an simple ORM for MySQL, I got a problem, if a defined struct missing some field:
type User struct {
ID int64
Username string
Password string
Email string
Comment string
}
var u = User{Username: "user_0001", Password: "password"}
Some fields of User didn't given a value, then it's value will be a zeroed value, such as string ""
, bool false
, integer 0
and so on.
So I am using reflect
to get field name and value, generate a sql to insert row.
INSERT INTO User (Id, Username, Password, Email, Comment) Values (0, "user_0001", "password", , ,)
You can see there has some zeroed value of string, if I detect empty string ""
and skip them, I may skip normal value.
答案1
得分: 2
处理可能为NULL
的数据库列,可以使用指针,就像Friedrich Große建议的那样,或者使用db
包中的Null...
变体,例如sql.NullString
。
要使用Null变体,结构体应该是这样的:
type User struct {
ID int64
Username string
Password string
Email sql.NullString
Comment sql.NullString
}
然后,您可以通过检查NullString.Valid
来检测值是否已设置。使用NullString
的缺点是,在打印或编组它们时,您必须添加特殊情况,因为它们不实现Stringer
接口,也不实现MarshalJSON
或UnmarshalJSON
。您还必须记住在设置字符串的值时手动设置NullString.Valid
。
例如,像这样的测试:
func TestNullString(t *testing.T) {
s := sql.NullString{}
t.Log(s)
s.String = "Test"
s.Valid = true
t.Log(s)
}
输出:
null_string_test.go:21: { false}
null_string_test.go:25: {Test true}
要打印NullString
,您必须这样做:
func TestNullString(t *testing.T) {
s := sql.NullString{}
t.Log(s.String)
s.String = "Test"
s.Value = true
t.Log(s.String)
}
输出:
null_string_test.go:21:
null_string_test.go:25: Test
英文:
To handle database columns that may be NULL
, you can either use pointers as Friedrich Große suggests, or use the Null...
-variants found in the db
package, for instance sql.NullString
.
To use the Null-variants, the struct would be
type User struct {
ID int64
Username string
Password string
Email sql.NullString
Comment sql.NullString
}
You can then detect of a value is set by checking NullString.Valid
. The downside of using NullString
is that you have to add special cases when printing or marshaling them, as they don't implement the Stringer
interface, nor MarshalJSON
or UnmarshalJSON
. You also have to remember to set NullString.Valid
manually when setting the value of the string.
For instance, a test like
func TestNullString(t *testing.T) {
s := sql.NullString{}
t.Log(s)
s.String = "Test"
s.Valid = true
t.Log(s)
}
Prints
null_string_test.go:21: { false}
null_string_test.go:25: {Test true}
To print a NullString
you have to instead do
func TestNullString(t *testing.T) {
s := sql.NullString{}
t.Log(s.String)
s.String = "Test"
s.Value = true
t.Log(s.String)
}
Which prints:
null_string_test.go:21:
null_string_test.go:25: Test
答案2
得分: 1
你可以将一个空字符串插入到你的表列中。如果真的很重要要区分零值和完全缺少值之间的区别,你需要使用指针。
type User struct {
ID int64
Username *string
}
这样会将零值更改为nil
,这样你就可以将其与""
区分开来。
缺点是这使得这种类型不太容易使用(在实践中经常会忘记进行nil
检查),而且你必须解引用该字段才能获得实际的字符串。
在你的具体示例中,我不明白为什么你需要担心空值。你不能只将""
插入到数据库中,并在代码中强制执行验证(非空性),而不使用数据库约束吗?
英文:
You can always just insert an empty string into your table column. If it is truly important to know the difference between the zero value or complete absence of a value you would need to use pointers.
type User struct {
ID int64
Username *string
}
This changes the zero value to be nil
so you can distinguish that from ""
.
The downside is that this makes this type less easy to use (nil
checks are often forgotten in practice) and you have to dereference that field to get the actual string.
In your specific example I don't see why you need to worry about the empty value at all. Can't you just insert ""
into the database and enforce validation (non-emptiness) in your code instead of using database constraints?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论