问答

Go 接口赋值的问题

作者:admin 2021-08-05 我要评论

问题描述 ????????在《Go语言编程》 里面讲接口赋值的时候,对对象实例赋值给接口做了如下案例 : type Integer intfunc (a Integer) Less(b Integer) bool { ret...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

问题描述

????????在《Go语言编程》 里面讲接口赋值的时候,对对象实例赋值给接口做了如下案例 :

type Integer int

func (a Integer) Less(b Integer) bool {
    return a < b
}

func (a *Intger) Add(b Integer) {
    *a += b
}

// 定义接口
type LessAdder interface {
    Less(b Integer) bool
    Add(b Integer) 
}

func main() {
    var a Integer = 1
    var b LessAdder = &a   // (1)
}

???????? (1) 哪里说的是会自动生成一个新的方法

func (a *Integer) Less( b Integer) bool {
    return (*a) < b
}

????????这样我们引申一下, 将Add函数也修改如下

func (a Integer) Add(b Integer) {
    a += b
}

// 赋值给接口
var a Integer = 1
var b LessAdder = &a   // (2)

????????同理应该也会生成一个新的函数(如下代码):

func (a * Integer) Add(b Integer) {
    (*a) += b
}

????????按新生成函数形式来看, 其调用应该会修改 a 指针的指向的值, 但如下代码结果依然是1, 请问这是为什么。

var a Integer = 1
var b LessAdder = &a
b.Add(100)
fmt.Println(a)   // 1
###

不会生成一个新方法的。

Method Set:

Method sets

A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T). Further rules apply to structs containing embedded fields, as described in the section on struct types. Any other type has an empty method set. In a method set, each method must have a unique non-blank method name.

Receiver 是 T 的方法可以直接给 *T 用。

###

先说结论,Go 会判断值或指针作为方法的 caller 时,对应的方法集(method set)是否合法,但不会帮你“生成”新的方法,至少我没有从官网的文档里看到类似的说法。

楼上@fefe 已经说得很明确了,我这里只是补充一下。

首先,Go 判断接口是否被实现时会对 method set 进行判断。比如这样写的时候:

var a Integer = 1
var b LessAdder = a

如果 Integer 实现了下面的方法

func (a *Intger) Add(b Integer) {
    *a += b
}

那么就会报错

cannot use a (type Integer) as type LessAdder in assignment:
Integer does not implement LessAdder (Add method has pointer receiver)

其次,Go 在调用方法的时候,会根据 method 的 receiver 类型对 caller 做一些“转换”,比如取值或者解引用。最后的代码中 a 的直没有改变是因为调用 Add 的时候 Go 帮你对b进行了解引用,然后将(*b)的值作为一个 value 类型的 caller 传递到 Add里。这样说可能还是不太形象,结合官网对于 receiver 等价于形参的解释,实际上应该是这样的:Add(*b, 100).

所以 a 没有改变不是因为没有“生成”新方法,而是 Go 帮你做了一次值拷贝。

深究的话还是有很多不是确切知道的点,比如什么情况下会做 method set 的判断,以及什么情况下不会对 caller 取地址,等等。以上,我也是查查官网文档,如果有理解不对的地方请随时指出来。

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • Go 接口赋值的问题

    Go 接口赋值的问题

  • 做过开发、单元测试、系统测试、

    做过开发、单元测试、系统测试、

  • vant的list组件,用于定位实现的瀑布流

    vant的list组件,用于定位实现的瀑布流

  • 手动刷新网页时如何添加请求头?

    手动刷新网页时如何添加请求头?

腾讯云代理商
海外云服务器