go 规范:文档为空检查值方法 ```markdown 规范:文档为空检查值方法 ```

dkqlctbz  于 2个月前  发布在  Go
关注(0)|答案(8)|浏览(35)

你使用的Go版本是什么(go version)?

go version go1.12 linux/amd64

你做了什么?

package main

import (
	"fmt"
)

type S struct {}

func (S) M(n int) {
	fmt.Println(n)
}

type T struct {
	*S
}

type I interface {
	M(n int)
}

func foo() {
	var v = &T{}
	var i I = v
	f := i.M // ok
	v.S = &S{}
	f(111) // 111
}

func bar() {
	var v = &T{}
	f := v.M // panic
	v.S = &S{}
	f(111)
}

func main() {
	foo()
	bar()
}

你觉得会看到什么?

相同的行为

你看到了什么?

不同的行为。

zvokhttg

zvokhttg2#

我认为这个行为在规范中已经明确指定:
与选择器一样,对非接口方法的值接收器的指针引用会自动解引用该指针:pt.Mv等同于(*pt).Mv。
与方法调用一样,对非接口方法的指针接收器的可寻址值的引用会自动获取该值的地址:t.Mp等同于(&t).Mp。
此外,#47863 添加了一个关于如何评估接收者的例子,我们现在可以关闭这个问题吗?cc @griesemer@mdempsky@ianlancetaylor

wmvff8tz

wmvff8tz3#

这是我在玩这个#32021时发现的另一个bug,它已经关闭了。但我认为反射和直接代码之间也存在不一致性。

wixjitnu

wixjitnu5#

f := v.M的情况下,我们在创建方法值的点处检查一个nil指针。我们这样做是因为在方法值被调用时检查nil指针会导致令人困惑的回溯。在f := i.M的情况下,我们检查i不是nil,但我们不检查该值本身是否包含一个nil指针。
所以这个工作是按照预期进行的,为了避免在生成的 Package 函数中发生nil解引用,但是,你是对的,它并不完全一致。

xcitsw88

xcitsw886#

我会说这种不一致需要更好地记录下来,因为这会让使用Go的人感到惊讶。请将此作为一个文档问题。

svmlkihl

svmlkihl7#

在我看来,#32021的不一致性比当前问题更严重。我认为,如果可能的话,反射代码实现和直接代码实现应该相互一致。
就个人而言,我更倾向于当前的反射实现方式。

slhcrj9b

slhcrj9b8#

如果我们记录某事,那将是对语言规范的更改,说明你不能创建一个nil指针的方法值,也不能在指针为nil时创建一个提升方法的方法值。换句话说,在创建方法值时进行所有nil检查,而不是在调用时进行。
对于接口类型,如果接口值是nil,则不能创建值方法。然而,我们不检查接口值中存储的任何内容,我不确定我们是否可以这样做。

相关问题