2025-04-11 05:00:04

围棋中的零检测

我在Go中看到了很多检测nil的代码,像这样:

if err != nil { 
    // handle the error    
}

然而,我有一个像这样的结构:

type Config struct {
    host string  
    port float64
}

和config是config的一个实例,当我这样做:

if config == nil {
}

有编译错误,说: 不能将nil转换为Config类型


当前回答

在Go 1.13及以后的版本中,您可以使用Value。反射包中提供的IsZero方法。

if reflect.ValueOf(v).IsZero() {
    // v is zero, do something
}

除了基本类型,它还适用于Array, Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer和Struct。参考这个。

其他回答

编译器将错误指向你,你在比较一个结构实例和nil。它们不是同一类型的,所以它认为这是一个无效的比较,并对你大喊大叫。

这里要做的是将指向配置实例的指针与nil进行比较,这是一个有效的比较。要做到这一点,你可以使用golang new内置,或者初始化一个指向它的指针:

config := new(Config) // not nil

or

config := &Config{
                  host: "myhost.com", 
                  port: 22,
                 } // not nil

or

var config *Config // nil

然后你就能检查是否

if config == nil {
    // then
}

除了Oleiade,请参阅零值规范:

When memory is allocated to store a value, either through a declaration or a call of make or new, and no explicit initialization is provided, the memory is given a default initialization. Each element of such a value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.

正如你所看到的,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 }

我已经创建了一些示例代码,使用我能想到的各种方式创建新变量。看起来,前3种方法创建值,后两种方法创建引用。

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}

在Go 1.13及以后的版本中,您可以使用Value。反射包中提供的IsZero方法。

if reflect.ValueOf(v).IsZero() {
    // v is zero, do something
}

除了基本类型,它还适用于Array, Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer和Struct。参考这个。

你也可以检查像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
    } 
}

http://play.golang.org/p/RXcE06chxE