我在Go中看到很多检测nil的代码,如下所示:
if err != nil {
// handle the error
}
但是,我有一个这样的结构:
type Config struct {
host string
port float64
}
而config是Config的实例,当我这样做时:
if config == nil {
}
有编译错误,说:无法将nil转换为Config类型
我在Go中看到很多检测nil的代码,如下所示:
if err != nil {
// handle the error
}
但是,我有一个这样的结构:
type Config struct {
host string
port float64
}
而config是Config的实例,当我这样做时:
if config == nil {
}
有编译错误,说:无法将nil转换为Config类型
Answers:
编译器将错误指向您,您正在比较结构实例和nil。它们的类型不同,因此将其视为无效的比较并大吼大叫。
您要在此处执行的操作是将指向您的配置实例的指针与nil进行比较,这是有效的比较。为此,您可以使用new内置的golang 或初始化指向它的指针:
config := new(Config) // not nil
要么
config := &Config{
host: "myhost.com",
port: 22,
} // not nil
要么
var config *Config // nil
然后,您将能够检查
if config == nil {
// then
}
var config &Config // nil
应该是:var config *Config
var config *Config
崩溃invalid memory address or nil pointer dereference
。也许我们需要var config Config
除了Oleiade之外,请参见零值规范:
当通过声明或调用make或new分配内存以存储值时,没有提供任何显式初始化,则为该内存提供默认初始化。此值的每个元素的类型均设置为零:布尔值为false,整数值为0,浮点数为0.0,字符串为“”,指针,函数,接口,切片,通道和映射为nil。该初始化是递归完成的,因此,例如,如果未指定任何值,则结构数组的每个元素的字段都将为零。
如您所见,nil
不是每种类型的零值,而是指针,函数,接口,片,通道和映射的零值。这就是为什么config == nil
不是错误
的原因&config == nil
。
要检查你的结构是未初始化你必须检查每一个成员提供其相应的零值(例如host == ""
,port == 0
等)或具有通过内部初始化方法设置一个私有字段。例:
type Config struct {
Host string
Port float64
setup bool
}
func NewConfig(host string, port float64) *Config {
return &Config{host, port, true}
}
func (c *Config) Initialized() bool { return c != nil && c.setup }
time.Time
要有一种IsZero()
方法的原因。但是你也可以这样做var t1 time.Time; if t1 == time.Time{}
,你可以同时做if config == Config{}
检查所有的现场为你(结构平等是顺利的定义)。但是,如果您有很多字段,效率就不高。而且,零值也许是一个合理且可用的值,所以传入一个并没有什么特别的。
func (c *Config) Initialized() bool { return !(c == nil) }
我创建了一些示例代码,这些代码使用我能想到的各种方式来创建新变量。看起来前三种创建值的方式,后两种创建引用。
package main
import "fmt"
type Config struct {
host string
port float64
}
func main() {
//value
var c1 Config
c2 := Config{}
c3 := *new(Config)
//reference
c4 := &Config{}
c5 := new(Config)
fmt.Println(&c1 == nil)
fmt.Println(&c2 == nil)
fmt.Println(&c3 == nil)
fmt.Println(c4 == nil)
fmt.Println(c5 == nil)
fmt.Println(c1, c2, c3, c4, c5)
}
输出:
false
false
false
false
false
{ 0} { 0} { 0} &{ 0} &{ 0}
您也可以检查struct_var == (struct{})
。这不允许您与nil进行比较,但是会检查它是否已初始化。使用此方法时要小心。如果您的结构的所有字段的值都可以为零,那么您将不会花费很多时间。
package main
import "fmt"
type A struct {
Name string
}
func main() {
a := A{"Hello"}
var b A
if a == (A{}) {
fmt.Println("A is empty") // Does not print
}
if b == (A{}) {
fmt.Println("B is empty") // Prints
}
}