go 有关 nil 的一个疑问?

2022-10-18 16:20:00 +08:00
 yujianwjj

今天突然意识到一个问题:go 的代码中,关于调用结构体指针绑定的方法的时候,方法里面似乎都没有判断该指针是否为 nil 的情况。

type A struct {
	a int
}

func (a *A) Run() {
	fmt.Print(a.a)
}

func TestA(t *testing.T) {
	var a *A
	a.Run()
}

以上代码会报错,原因也很明显,a 为 nil, a.Run() 方法中,访问 a.a 报错。 看了一下自己之前写的所有 go 代码,所有 结构体指针绑定的方法里面,都没有判断是否为 nil 的情况。

3764 次点击
所在节点    Go 编程语言
36 条回复
airplayxcom
2022-10-18 16:26:06 +08:00
会 go 不会 go 的都哑口无言了
0o0O0o0O0o
2022-10-18 16:26:50 +08:00
在一些项目源码里见到过判断的,不过我是觉得没必要。
randm
2022-10-18 16:33:24 +08:00
会报 panic
coderxy
2022-10-18 16:36:15 +08:00
if a!=nil ?
hsfzxjy
2022-10-18 16:38:21 +08:00
这种一般是调用者保证它非 nil
warlock
2022-10-18 16:38:36 +08:00
这取决于哪里需要关心 a 为 nil 这件事
charmToby
2022-10-18 16:41:37 +08:00
```golang
type A struct {
a int
}

func (a *A) Run() {
fmt.Print(a.a)
}

func NewA()*A{
return &A{}
}

func TestA(t *testing.T) {
//var a *A // 这一步只是声明了一个变量 a 为 结构体 A 指针类型,没有实例化
//a.Run()
a := NewA() // 一般都是这样去实例化
a.Run()
}
```
XyIsMy
2022-10-18 16:45:31 +08:00
你这代码只是声明了 变量 a 是 A 类型。没有实例化
fuxiaohei
2022-10-18 16:48:55 +08:00
判不判断 nil 看需求,有时候结构体绑定的方法是当函数来用的
```golang

import "fmt"

type A struct {
a int
}

func (a *A) Run() {
fmt.Print(a.a)
}

func main() {
var fn = (*A).Run
fmt.Println(fn)
fn(&A{111})
}

```
zhs227
2022-10-18 16:50:51 +08:00
变量没初始化不能怪函数绑定。
pkoukk
2022-10-18 16:54:53 +08:00
此时,a==nil
所以,a.Run() == nil.Run()
作为一个 nil,怎么可能执行的了(a *A) Run() 这个函数呢?
这和 go 没有任何关系
JKeita
2022-10-18 17:02:30 +08:00
你只是声明了个 A 指针类型变量,肯定会报错啊。
tianyou666shen
2022-10-18 17:07:43 +08:00
家人们 见鬼了
声明变量但不初始化对象 居然不能调用对象方法
CyJaySong
2022-10-18 17:11:11 +08:00
func TestA(t *testing.T) {
var a = new(A)
a.Run()
}

试试呢😜
zhuweiyou
2022-10-18 17:22:19 +08:00
要么 new, 要么 &A{} 吧
siloong
2022-10-18 17:26:26 +08:00
想到了开心的事

```golang
type A struct{}

func (*A) hello() {
fmt.Println("hello, world")
}

func main() {
var a *A
fmt.Printf("a is nil? %v\n", a == nil)
a.hello()
}
```
ArianX
2022-10-18 17:29:09 +08:00
@pkoukk 是可以执行的,a 是一个有类型的 nil ,可以调用这个类型的指针方法
sardina
2022-10-18 17:32:31 +08:00
我要调某个结构体的方法,但是我不初始化这个结构体,哎,我就是玩
Citrus
2022-10-18 17:33:03 +08:00
@siloong 没毛病啊,你的 hello 又没用 A 里的东西,当然能跑。改成这样比较有意思:

type A struct{}

func (*A) hello() {
fmt.Println("hello, world")
}

func main() {
var a *A
var b interface{}
b = a
fmt.Printf("a is nil? %v\n", a == nil)
fmt.Printf("b is nil? %v\n", b == nil)
a.hello()
}
pkoukk
2022-10-18 17:54:20 +08:00
@ArianX 居然真的可以,涨知识了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/887817

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX