douyinliu8813 2018-12-10 07:50 采纳率: 100%
浏览 416
已采纳

Golang接口上的指针接收器和值接收器

我刚接触过golang,而且刚刚才掌握了它的诀窍。通过Tour of Go,然后加上我自己的理解来使用它。我在Interfaces上,开始用我自己的理解来实现。这是它的链接:Go PlayGround Link

步骤1:我创建了3种类型:int、struct和接口。

package main

import (
    "fmt"
)

type MyInt int

type Pair struct {
    n1, n2 int
}

type twoTimeable interface {
    result() (int, int)
}

步骤2:然后,我为指针接收器实现了twoTimeable,因为它改变了底层值。

func (p *Pair) result() (int, int) {
    p.n1 = 2 * p.n1
    p.n2 = 2 * p.n2
    return p.n1, p.n2
}

func (m *MyInt) result() (int, int) {
    *m = 2 * (*m)
    return int(*m), 0
}

步骤3:然后在主函数中声明并分配Myint、结对及其相应的指针。我还声明了两个时间接口。

mtemp := MyInt(2)
var m1 MyInt
var m2 *MyInt
var p1 Pair
var p2 *Pair
m1, m2, p1, p2 = MyInt(1), &mtemp, Pair{3, 4}, &Pair{5, 6}
var tt twoTimeable

fmt.Println(" Values  : ", m1, *m2, p1, *p2, tt)

第4步:分配Myint、结对和它们的指针。

tt = m1
fmt.Println(tt.result())
fmt.Printf("Value of m1 %v
", m1)

tt = m2
fmt.Println(tt.result())
fmt.Printf("Value of m2 %v
", *m2)

tt = p1
fmt.Println(tt.result())
fmt.Printf("Value of p1 %v
", p1)

tt = p2
fmt.Println(tt.result())
fmt.Printf("Value of p2 %v
", *p2)

显示的错误:

prog.go:41:5: cannot use m1 (type MyInt) as type twoTimeable in assignment:
    MyInt does not implement twoTimeable (result method has pointer receiver)
prog.go:49:5: cannot use p1 (type Pair) as type twoTimeable in assignment:
    Pair does not implement twoTimeable (result method has pointer receiver)

我知道M1和p1是不可寻址的,这就是为什么它不能编译。但是,如果我使用p1或m1p1/m1.run()(自动取消FTW),那么方法结果()就可以正常工作了。

在步骤2中,当我将指针接收器更改为值接收者,并将m改为m时(我知道输出的变化):

func (p Pair) result() (int, int) {
    p.n1 = 2 * p.n1
    p.n2 = 2 * p.n2
    return p.n1, p.n2
}

func (m MyInt) result() (int, int) {
    m = 2 * (m)
    return int(m), 0
}

它就没有显示编译错误了。但是对于m2和p2就不能这样做,因为没有使用Myint和结对来实现结果。当接口方法实现有指针接收时,则不能容纳非指针。

Q1:为什么可以在值接收接口方法(PMyint)的结果()上使用指针(TT=m2),而在指针接收接口方法(PMyint)的结果()上使用值(TT=M1)?

现在让我们恢复到指针接收器。

如果函数接受Param(TTtwoTimeable),那么是否有一种方法,无论TT是类型指针还是非类型指针,我都能够调用tt.Result(),给定的结果()只定义为指针接收器?

看下面的代码:

func doSomething(tt twoTimeable) {
    temp1, temp2 := tt.result()
    fmt.Print("doing something with ", temp1, temp2)
} 

由于TT可以是任何预定义的类型(指针或非指针),因此param似乎不像是一个解决方案,或者我是否依赖于函数的用户来提供指针?如果我不需要更改基础值,例如使用值接收器,那这就不是个问题,因为TT可以保存值或指向该值的指针。

在线等回复。

  • 写回答

3条回答 默认 最新

  • dqdz6464 2018-12-10 08:37
    关注

    Q1 : Why it is fine to use pointers on value receiver methods but not vice vers?

    Because the language spec say it it fine: https://golang.org/ref/spec#Method_sets :

    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).

    (A possible reason why the spec is like this: Convenience.)

    For the rest of the question: I do not have the slightest idea what you are asking. The code of do Something is totally fine. You invoke result on tt which is any type implementing the result() (int, int) method. Whether this type is a pointer type or not is of no interest. You get two ints back from this method call and can do whatever you want with these ints.

    (Regarding the "pointer to interface" part: Yes. It is technically possible to do ttp *twoTimetable. But you never need this. Never. (Of course this is a lie but the case you need it is so rare and delicate that you really never need this as a beginner and once you do need it you will know how to use it.) There is one thing to remember here: You never do "pointer to interface".)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料