Go中的字符串是一个值。因此,一个字符串不能被nil 。
x := "I am a string!"
x = nil // Won't compile, strings can't be nil in Go
然而,一个指向字符串的指针(或*string )可以是nil 。
var x *string
x = nil // Compiles! String pointers in GoLang can be nil
一个好的经验法则是使用普通字符串,除非你需要 nil 。正常的字符串在Go中使用起来更容易、更安全。指针需要你写更多的代码,因为你需要在取消引用之前检查*string 是否有一个值。
func UseString(s *string) error {
if s == nil {
temp := "" // *string cannot be initialized
s = &temp // in one statement
}
value := *s // safe to dereference the *string
}
一个空的字符串值"" 和nil 是不一样的。在编程时,如果你想不出需要nil 的原因,那么你可能不需要或不想要它。
那么,什么时候我应该使用字符串的指针呢?
有的时候你应该使用*string 。例如,当把json或yaml(或任何东西)反序列化为一个结构时,你可能应该对结构属性使用*string 。
考虑一下这样的代码:一个json文档被反序列化成一个由普通字符串属性组成的结构。
package main
import (
"encoding/json"
"fmt"
)
type Config struct {
Environment string
Version string
HostName string
}
func (c *Config) String() string {
return fmt.Sprintf("Environment: '%v'\nVersion:'%v'\nHostName: '%v'",
c.Environment, c.Version, c.HostName)
}
func main() {
jsonDoc :=`
{
"Environment" : "Dev",
"Version" : ""
}`
conf := &Config{}
json.Unmarshal([]byte(jsonDoc), conf)
fmt.Println(conf) // Prints
// Environment: 'Dev'
// Version:''
// HostName: ''
}
你会注意到,Version 和HostName 都被存储为空字符串。对于Version ,这是正确的行为,但是HostName 真的应该是一个空字符串吗?
这个问题的答案取决于你的程序。如果一个缺失的属性被解读为一个空字符串是可以接受的,那么就没有问题了。换句话说,如果你将处理缺失的json属性和空的json属性是一样的,那么就使用一个正常的字符串。
但是,如果"" 是一个有效的配置值HostName ,但是缺失的属性是无效的呢?
答案是:使用一个*string 。
package main
import (
"encoding/json"
"fmt"
)
type ConfigWithPointers struct {
Environment *string // pointer to string
Version *string
HostName *string
}
func (c *ConfigWithPointers) String() string {
var envOut, verOut, hostOut string
envOut = "<nil>"
verOut = "<nil>"
hostOut = "<nil>"
if c.Environment != nil { // Check for nil!
envOut = *c.Environment
}
if c.Version != nil {
verOut = *c.Version
}
if c.HostName != nil {
hostOut = *c.HostName
}
return fmt.Sprintf("Environment: '%v'\nVersion:'%v'\nHostName: '%v'",
envOut, verOut, hostOut)
}
func main() {
jsonDoc :=
`
{
"environment" : "asdf",
"hostName" : ""
}
`
conf := &ConfigWithPointers{}
json.Unmarshal([]byte(jsonDoc), conf)
fmt.Println(conf) // Prints the following:
// Environment: 'asdf'
// Version:'<nil>'
// HostName: ''
}
请注意,使用*string ,你现在可以区分缺失的属性或null 值与json文档中的空字符串值。
tl;dr; 如果你需要nil ,才使用字符串指针*string 。否则,使用一个普通的字符串