正确区分未设置(nil)和空值/空白值。

huangapple go评论83阅读模式
英文:

Properly distinguish between not set (nil) and blank/empty value

问题

在Go语言中,区分结构体中的值是未设置还是为空的正确方式是使用指针类型。例如,给定以下结构体:

type Organisation struct {
    Category *string
    Code     *string
    Name     *string
}

如果需要知道某个字段是未设置还是被用户保存为空白值,可以将该字段声明为指针类型。如果字段的指针为nil,则表示该字段未设置;如果字段的指针非nil,但指向的值为空字符串,则表示该字段被保存为空白值。

同时,为了正确地将null或空字符串持久化到数据库中,可以根据字段的指针值进行判断和处理。如果字段的指针为nil,则将其持久化为null;如果字段的指针非nil,但指向的值为空字符串,则将其持久化为空字符串。

希望对你有帮助!如果你还有其他问题,请随时提问。

英文:

Whats the correct way in go to distinguish between when a value in a struct was never set, or is just empty, for example, given the following:

type Organisation struct {
	Category string
	Code     string
	Name     string
}

I need to know (for example) if the category was never set, or was saved as blank by the user, should I be doing this:

type Organisation struct {
	Category *string
	Code     *string
	Name     *string
}

I also need to ensure I correctly persist either null or an empty string to the database

I'm still learning GO so it is entirely possible my question needs more info.

答案1

得分: 6

string类型的零值是空字符串,你无法区分这两者。

如果你正在使用database/sql包,并且需要区分NULL和空字符串,可以考虑使用sql.NullString类型。它是一个简单的结构体,用于跟踪NULL状态:

type NullString struct {
    String string
    Valid  bool // 如果String不为NULL,则Valid为true
}

你可以将数据扫描到这个类型中,并将其用作查询参数,database/sql包会为你处理NULL状态。

英文:

The zero value for a string is an empty string, and you can't distinguish between the two.

If you are using the database/sql package, and need to distinguish between NULL and empty strings, consider using the sql.NullString type. It is a simple struct that keeps track of the NULL state:

type NullString struct {
        String string
        Valid  bool // Valid is true if String is not NULL
}

You can scan into this type and use it as a query parameter, and the package will handle the NULL state for you.

答案2

得分: 5

Google的协议缓冲区(https://code.google.com/p/goprotobuf/)使用指针来描述可选字段。

生成的对象提供了GetFoo方法,它可以避免测试nil值的繁琐(如果a.Foo为nil,则a.GetFoo()返回一个空字符串,否则返回*a.Foo)。

当你想要编写字面结构体时(例如在测试中),这会引入一些麻烦,因为&"something"不是生成指向字符串的指针的有效语法,所以你需要一个辅助函数(参见,例如,协议缓冲区库的proto.String源代码)。

// String是一个辅助函数,它分配一个新的字符串值来存储v,并返回指向它的指针。
func String(v string) *string {
        return &v
}

总的来说,使用指针来表示可选字段并不是没有缺点的,但它肯定是一个可行的设计选择。

英文:

Google's protocol buffers (https://code.google.com/p/goprotobuf/) use pointers to describe optional fields.

The generated objects provide GetFoo methods which take the pain away from testing for nil (a.GetFoo() returns an empty string if a.Foo is nil, otherwise it returns *a.Foo).

It introduces a nuisance when you want to write literal structs (in tests, for example), because &"something" is not valid syntax to generate a pointer to a string, so you need a helper function (see, for example, the source code of the protocol buffer library for proto.String).

// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string {
        return &v
}

Overall, using pointers to represent optional fields is not without drawbacks, but it's certainly a viable design choice.

答案3

得分: 4

标准的database/sql包提供了一个NullString结构体(成员只有String stringValid bool)。为了处理一些重复的持久化工作,你可以考虑使用一个对象关系管理器,比如gorp

我曾经调查过是否有一种方法可以区分两种类型的空字符串,只是出于好奇,并没有找到。对于[]byte[]byte{} == []byte(nil)目前返回false,但我不确定规范是否保证这一点始终为真。无论如何,似乎最实际的做法是顺其自然,使用NullString

英文:

The standard database/sql package provides a NullString struct (members are just String string and Valid bool). To take care of some of the repetitive work of persistence, you could look at an object-relational manager like gorp.

I looked into whether there was some way to distinguish two kinds of empty string just out of curiosity, and couldn't find one. With []bytes, []byte{} == []byte(nil) currently returns false, but I'm not sure if the spec guarantees that to always remain true. In any case, it seems like the most practical thing to do is to go with the flow and use NullString.

huangapple
  • 本文由 发表于 2014年5月19日 07:23:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/23727866.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定