doukanwa6872 2015-06-26 05:56
浏览 46

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

I am new to Go, and I am studying its interface feature.

Here is the code:

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)

}

And it will output the the following:

*main.Integer
true
2

Well, this works pretty well.

The Point is: How var b LessAdder = &a works. Does the pointer auto-dereference happens right here, or when b invokes member method?

The output *main.Integer tells us that b is a pointer to type Integer, hence it is the second case.

Then the tricky thing comes: when I add fmt.Pringln(*b) to the code, the compiler comes with an error:

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

And it confuses me. Since b is a pointer type to Integer, then dereferencing it should work. But why not?

  • 写回答

2条回答 默认 最新

  • douchun1948 2015-06-26 06:01
    关注

    Your last sentence:

    "Since b is a pointer type to Integer, then dereferencing it should work."

    Stop right there. b is not a variable of pointer type and therefore you can't dereference it.

    It is a variable of interface type which is schematically a pair of a value and a type (value,type), holding &a as the value and *Integer as the type (blog article The Laws of Reflection, section The representation of an interface).

    This is a declaration of a variable of pointer type, *Integer:

    var ip *Integer
    

    And this is one of an interface type:

    var intf LessAdder
    

    When you do this:

    var b LessAdder = &a
    

    What happens is that an interface value (of type LessAdder) is created automatically/implicitly which will hold the value &a (and the type *Integer). This is a valid operation because the type of &a (which is *Integer) implements the interface LessAdder: the method set of *Integer is a superset of the interface LessAdder (in this case they are equal, the method set of an interface type is its interface).

    Now when you call b.Less(2), since Less() has a value receiver, the pointer will be dereferenced and a copy of the pointed value will be made and used/passed as the value receiver of the method Less().

    fmt.Println(reflect.TypeOf(b)) doesn't lie, but it will print the dynamic type of b. The dynamic type of b is indeed *Integer, but the static type of b is LessAdder and the static type is what determines what you can do with a value and what operators or methods are allowed on it.

    评论

报告相同问题?

悬赏问题

  • ¥15 opencv图像处理,需要四个处理结果图
  • ¥15 无线移动边缘计算系统中的系统模型
  • ¥15 深度学习中的画图问题
  • ¥15 java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条
  • ¥15 Python报错怎么解决
  • ¥15 simulink如何调用DLL文件
  • ¥15 关于用pyqt6的项目开发该怎么把前段后端和业务层分离
  • ¥30 线性代数的问题,我真的忘了线代的知识了
  • ¥15 有谁能够把华为matebook e 高通骁龙850刷成安卓系统,或者安装安卓系统
  • ¥188 需要修改一个工具,懂得汇编的人来。