在 Go 中为接口分配指针时与隐式指针取消引用混淆

我是 Go 的新手,我正在研究它的界面功能。


这是代码:


package main


import (

        "fmt"

        "reflect"

)


type Integer int


func (a Integer) Less(b Integer) bool {

        return a < b

}


func (a *Integer) Add(b Integer) {

        *a += b

}


type LessAdder interface {

        Less(b Integer) bool

        Add(b Integer)

}


var a Integer = 1


var b LessAdder = &a


func main() {

        fmt.Println(reflect.TypeOf(b))

        fmt.Println(b.Less(2))

        b.Add(a)

        fmt.Println(a)


}

它将输出以下内容:


*main.Integer

true

2

嗯,这很好用。


重点是:如何var b LessAdder = &a运作。指针自动取消引用是在这里发生,还是在 b 调用成员方法时发生?


输出*main.Integer告诉我们 b 是指向 type 的指针Integer,因此是第二种情况。


然后棘手的事情来了:当我添加fmt.Pringln(*b)到代码中时,编译器出现错误:


 demo/demo1

./demo1.go:31: invalid indirect of b (type LessAdder)

这让我很困惑。由于b是指向 的指针类型Integer,因此取消引用它应该可以工作。但为什么不呢?


jeck猫
浏览 206回答 2
2回答

有只小跳蛙

你的最后一句话:“由于b是指向 的指针类型Integer,因此取消引用它应该可以工作。”停在那儿。b是不是指针类型的变量,因此,你不能解引用它。它是接口类型的变量,示意性地是一对值和类型 (value,type),&a作为值和*Integer作为类型(博客文章反射定律,接口的表示部分)。这是一个指针类型变量的声明*Integer:var&nbsp;ip&nbsp;*Integer这是一种接口类型:var&nbsp;intf&nbsp;LessAdder当你这样做时:var&nbsp;b&nbsp;LessAdder&nbsp;=&nbsp;&a发生的情况是LessAdder自动/隐式创建了一个接口值(类型),它将保存值&a(和类型*Integer)。这是一个有效的操作,因为的类型&a(这是*Integer)实现接口LessAdder:该方法集的*Integer是接口的一个超集LessAdder(在这种情况下,它们是相等的,一个接口类型的方法集为其接口)。现在,当您调用 时b.Less(2),由于Less()具有值接收器,指针将被取消引用,并且将制作指向值的副本并作为方法的值接收器使用/传递Less()。fmt.Println(reflect.TypeOf(b))不说谎,但它会打印出动态的类型b。的动态类型b确实是*Integer,但静态类型b是LessAdder,而静态类型决定了您可以对值做什么以及允许使用哪些运算符或方法。

森栏

LessAdder被声明为具有方法Less和的接口Add。由于Add是用 的接收者声明的*Integer,所以 a*Integer可以是 a&nbsp;LessAdder;一个Integer不能。当你这样做时var b LessAdder = &a,它是指向a存储在接口中的指针b。自动间接发生在对 的调用时b.Less(2),因为方法 on*Integer和方法 on 都Integer有助于 的方法集*Integer。您不能使用,*b因为虽然b&nbsp;包含*Integer,但它的静态类型是LessAdder,而不是*Integer。撇开接口的表示不谈,LessAdder不是指针类型,并且*b如果允许,则根本没有可表达的类型。您可以使用一个类型断言访问b作为Integer *一次;&nbsp;b.(*Integer)是 type 的表达式*Integer,并且*b.(*Integer)是Integer.&nbsp;如果 in 的值毕竟b不是 a&nbsp;*Integer,那么这两种方法都会导致运行时恐慌。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go