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

报告相同问题?

悬赏问题

  • ¥15 如何构建全国统一的物流管理平台?
  • ¥100 ijkplayer使用AndroidStudio/CMake编译,如何支持 rtsp 直播流?
  • ¥20 和学习数据的传参方式,选择正确的传参方式有关
  • ¥15 这是网络安全里面的poem code
  • ¥15 用js遍历数据并对非空元素添加css样式
  • ¥15 使用autodl云训练,希望有直接运行的代码(关键词-数据集)
  • ¥50 python写segy数据出错
  • ¥20 关于线性结构的问题:希望能从头到尾完整地帮我改一下,困扰我很久了
  • ¥30 3D多模态医疗数据集-视觉问答
  • ¥20 设计一个二极管稳压值检测电路