Golang中如何检测指针引用的结构体是否为nil

Golang中如何检测指针引用的结构体是否为nil

import (
	"fmt"
)

type str struct {
	a string
}

func main() {

	var p *str
	chk(p)

}

func chk(s interface{}) {
	fmt.Println("Check", s) // 这里打印的是nil
	if s == nil { // 但这里无法检查
		fmt.Println("It is null....")
	}
	fmt.Println("Hello, playground")
}
8 回复

这是我遇到的错误…我尝试了各种类型的值

更多关于Golang中如何检测指针引用的结构体是否为nil的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢Lutzhorn,

你的回复非常有用

还有一件事
如何仅检查值是否为空?

intstring 不能这样使用。但你为什么要将它们作为 interface{} 传递?你想要实现什么功能?

panic: reflect: call of reflect.Value.IsNil on string Value

goroutine 1 [running]:
reflect.Value.IsNil(0xee6e0, 0x195920, 0x98, 0x195920, 0x98, 0xf0740)
	/usr/local/go/src/reflect/value.go:1018 +0x160
main.chk(0xee6e0, 0x195920)
	/tmp/sandbox753849162/main.go:33 +0xc0
main.main()
	/tmp/sandbox753849162/main.go:21 +0x60
import (
	"fmt"
	"reflect"
)

var string1 string
var int1 int

type strtemp struct {
	newstr string
}
type str struct {
	a  string
	st *strtemp
}

func main() {
	var p *str
	chk(string1)
	chk(int1)
	chk(p)
}

func chk(s interface{}) {
	fmt.Printf("value=%v type=%t\n", s, s)
	// s的类型不是nil,所以以下条件为假
	if s == nil {
		fmt.Println("s is nil....")
	}
	// s的值为nil,以下条件为真
	if reflect.ValueOf(s).IsNil() {
		fmt.Println("value of s is nil")
	}
	fmt.Println("Hello, playground")
}

看看这个

package main

import (
	"fmt"
)

type str struct {
	a string
}

func main() {
	var p *str
	chk(p)
}

func chk(s interface{}) {
	fmt.Printf("value=%v type=%t\n", s, s)
	// s的类型不为nil,因此以下判断为false
	if s == nil {
		fmt.Println("It is null....")
	}
	fmt.Println("Hello, playground")
}

输出结果为

value=<nil> type=%!t(*main.str=<nil>)
Hello, playground

要成为nil,类型和值都必须为nil

另请参阅 https://u.lhorn.de/mo3Z

尝试这个:

package main

import (
	"fmt"
	"reflect"
)

type str struct {
	a string
}

func main() {
	var p *str
	chk(p)
}

func chk(s interface{}) {
	fmt.Printf("value=%v type=%t\n", s, s)
	// s的类型不是nil,所以以下条件为false
	if s == nil {
		fmt.Println("s is nil....")
	}
	// s的值为nil,以下条件为true
	if reflect.ValueOf(s).IsNil() {
		fmt.Println("value of s is nil")
	}
	fmt.Println("Hello, playground")
}

输出:

value=<nil> type=%!t(*main.str=<nil>)
value of s is nil
Hello, playground

另请参阅 https://u.lhorn.de/m65w

在Go语言中,当接口值包含一个具体的类型但值为nil时(比如*str类型的nil指针),直接与nil比较会返回false。这是因为接口值由类型和值两部分组成,虽然值为nil,但类型信息仍然存在。

以下是几种正确的检测方法:

方法1:使用反射包(reflect)

import (
    "fmt"
    "reflect"
)

type str struct {
    a string
}

func main() {
    var p *str
    chk(p)
}

func chk(s interface{}) {
    if s == nil {
        fmt.Println("It is nil")
        return
    }
    
    // 使用反射检查底层值是否为nil
    v := reflect.ValueOf(s)
    if v.Kind() == reflect.Ptr && v.IsNil() {
        fmt.Println("Pointer to struct is nil")
        return
    }
    
    fmt.Println("Not nil")
}

方法2:类型断言检查

func chk(s interface{}) {
    if s == nil {
        fmt.Println("It is nil")
        return
    }
    
    // 类型断言检查
    switch v := s.(type) {
    case *str:
        if v == nil {
            fmt.Println("*str is nil")
            return
        }
    default:
        fmt.Printf("Unknown type: %T\n", v)
    }
    
    fmt.Println("Not nil")
}

方法3:针对特定类型的检查函数

func chk(s interface{}) {
    if isNil(s) {
        fmt.Println("It is nil")
        return
    }
    fmt.Println("Not nil")
}

func isNil(i interface{}) bool {
    if i == nil {
        return true
    }
    
    switch v := i.(type) {
    case *str:
        return v == nil
    // 可以添加更多类型的检查
    default:
        return false
    }
}

方法4:直接传递指针(推荐)

func main() {
    var p *str
    chkPtr(p)
}

func chkPtr(s *str) {
    if s == nil {
        fmt.Println("Pointer is nil")
        return
    }
    fmt.Println("Pointer is not nil")
}

运行这些代码,当传入*str类型的nil指针时,会正确检测到nil状态。方法4是最简洁和高效的解决方案,因为它避免了接口包装的开销。

回到顶部