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类型


当前回答

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

其他回答

编译器将错误指向你,你在比较一个结构实例和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
}

在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

我已经创建了一些示例代码,使用我能想到的各种方式创建新变量。看起来,前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}

语言规范中提到了比较操作符的行为:

比较运算符

在任何比较中,第一个操作数必须可赋值给该类型 第二个操作数的,反之亦然。


可转让性

A value x is assignable to a variable of type T ("x is assignable to T") in any of these cases: x's type is identical to T. x's type V and T have identical underlying types and at least one of V or T is not a named type. T is an interface type and x implements T. x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a named type. x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type. x is an untyped constant representable by a value of type T.