Lec*_*eNi 3 pointers interface 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)
}
Run Code Online (Sandbox Code Playgroud)
它将输出以下内容:
*main.Integer
true
2
Run Code Online (Sandbox Code Playgroud)
嗯,这很好用.
要点是:如何var b LessAdder = &a运作.指针自动取消引用是在这里发生,还是在b调用成员方法时?
输出*main.Integer告诉我们b是指向类型的指针Integer,因此它是第二种情况.
然后棘手的事情来了:当我添加fmt.Pringln(*b)代码时,编译器出现错误:
demo/demo1
./demo1.go:31: invalid indirect of b (type LessAdder)
Run Code Online (Sandbox Code Playgroud)
它让我很困惑.既然b是指针类型Integer,那么取消引用它应该有效.但为什么不呢?
你的最后一句话:
"既然
b是指针类型Integer,那么取消引用它应该有效."
停在那儿.b是不是指针类型的变量,因此你不能解引用它.
它是一个接口类型的变量,它是一对值和一个类型(值,类型),保持&a为值和*Integer类型(博客文章反射的法则,部分接口的表示).
这是指针类型变量的声明,*Integer:
var ip *Integer
Run Code Online (Sandbox Code Playgroud)
这是一种接口类型:
var intf LessAdder
Run Code Online (Sandbox Code Playgroud)
当你这样做:
var b LessAdder = &a
Run Code Online (Sandbox Code Playgroud)
会发生什么是LessAdder自动/隐式创建接口值(类型),它将保存值&a(和类型*Integer).这是一个有效的操作,因为的类型&a(这是*Integer)实现接口LessAdder:该方法集的*Integer是接口的一个超集LessAdder(在这种情况下,它们是相等的,一个接口类型的方法集为其接口).
现在当你调用时b.Less(2),由于Less()有一个值接收器,指针将被解除引用,并且将生成指向值的副本并使用/传递作为方法的值接收器Less().
fmt.Println(reflect.TypeOf(b))不会撒谎,但它会打印动态类型b.b确实是动态类型*Integer,但静态类型b是LessAdder静态类型,它决定了你可以用一个值做什么,以及允许哪些操作符或方法.