一个合乎逻辑的解决方案是使用 Ainar-G 提到的*string。 This other answer 详细说明了获取指向值的指针的可能性(int64 但同样适用于string)。包装器是另一种解决方案。
只使用string
可选的string 表示string 加上1 个特定值(或状态)表示“不是字符串”(而是null)。
这 1 个特定值可以存储(信号)在另一个变量中(例如bool),您可以将string 和bool 打包到struct 中,我们到达了包装器,但这并没有'不适合“仅使用string”的情况(但仍然是一个可行的解决方案)。
如果我们只想坚持 string,我们可以从 string 类型的可能值中取出 1 个特定值(它具有“无限”可能值,因为长度不受限制(或者可能是因为它必须是int 但没关系)),我们可以将这个特定值命名为null 值,该值表示“不是字符串”。
表示null最方便的值是string的零值,也就是空的string:""。指定null 元素的便利之处在于,每当您创建string 变量而不显式指定初始值时,它将使用"" 进行初始化。此外,当从 map 查询值为 string 的元素时,如果键不在 map 中,也会产生 ""。
此解决方案适用于许多实际用例。例如,如果可选的string 应该是一个人的名字,那么一个空的string 并不真正意味着一个有效的人名,所以你首先不应该允许这样做。
当然,在某些情况下,空的string 确实代表string 类型的变量的有效值。对于这些用例,我们可以选择其他值。
在 Go 中,string 实际上是只读的字节片。请参阅博客文章Strings, bytes, runes and characters in Go,其中详细解释了这一点。
所以string 是一个字节切片,如果是有效文本,它是 UTF-8 编码的字节。假设您想在可选的string 中存储有效文本(如果您不这样做,那么您可以只使用[]byte 而不是可以具有nil 值),您可以选择string 值表示无效的 UTF-8 字节序列,因此您甚至不必做出妥协以从可能的值中排除有效文本。最短的无效 UTF-8 字节序列只有 1 个字节,例如 0xff(还有更多)。注意:您可以使用utf8.ValidString() 函数来判断string 值是否为有效文本(有效的UTF-8 编码字节序列)。
您可以将此特殊值设为const:
const Null = "\xff"
这么短也意味着检查string是否等于这个将非常快。
按照这个约定,你已经有了一个可选的string,它也允许空的string。
在Go Playground 上试试。
const Null = "\xff"
func main() {
fmt.Println(utf8.ValidString(Null)) // false
s := Null
fmt.Println([]byte(s)) // [255]
fmt.Println(s == Null) // true
s = "notnull"
fmt.Println(s == Null) // false
}