首页 文章

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

提问于
浏览
-1

This question is not as clear as I wanted to be I will ask a better question. But I do not want to marked duplicate on that. So I have flagged my own question. If you can help it to be deleted to not confuse the community. Please do the needful. Please do not downvote me while you are at it. Sorry to be unclear

我是golang的新手,只是掌握了它 .

我正在学习Tour of Go,然后以我自己的理解使用它 . 我在Interfaces并开始以我自己的理解实施 . 这是Go PlayGround Link

第1步:我将3种类型设为int,struct和interface

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步:然后我在main函数中声明并分配了MyInt,Pair及其相应的指针 . 我还声明了twoTimeable接口

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,Pair和它们的指针,称为已实现的方法并打印出来 .

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

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

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

tt = p2
fmt.Println(tt.result())
fmt.Printf("Value of p2 %v\n", *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)

我也读了this question,我得到了m1和p1不可寻址,这就是为什么它不会编译 . 但是如果我使用p1或m1 p1/m1.result() (自动解除引用FTW),方法result()将正常工作

*Now in Step 2 when I change the pointer receiver to value receiver, and change m to m(I am aware of change in Output)

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和* Pair的结果实现

这意味着如果接口方法实现具有值接收器tt可以保持指针和值 . 但是当接口方法实现有指针接收器时,它不能保持非指针 .

Q1:为什么在值接收器接口方法(p MyInt)result()上使用指针(tt = m2),而不是在指针接收器接口方法(p * MyInt)result()上使用值(tt = m1) .

现在让我们回到指针接收器 .

有没有一种方法,如果函数接受参数(tt twoTimeable)我将能够调用tt.result()而不管是否是指向类型的指针,给定result()仅用指针接收器定义 .

请参阅以下代码:

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

因为tt可以是任何预定义的类型(指针或不是指针),所以运行param(tt * twoTimeable,如果我甚至可以这样做)似乎不是解决方案,或者我依赖于函数用户来提供指针 . 如果我不必更改基础值,即使用值接收器它不是一个问题,因为tt可以保持值或指针

我总是接受回答 .

3 回答

  • 0

    不应该为m2和p2,因为现在没有使用* MyInt和* Pair实现结果

    不 . 您正在混淆不同的事情并误解结果 .

    Go允许您在大多数情况下省略指针解除引用 .

    type Pair struct {
        n1, n2 int
    }
    var pp *Pair = ...
    fmt.Println(pp.n1)
    

    看到最后一行? pp 是指向Pair的指针,但不需要写 (*pp).n1 . 将自动插入此解除引用(它是C中 -> 运算符的自动变体) .

    你的m2和p2只是包含指针的变量 . 如果需要,这些指针将被解除引用 . 这与指针/值接收器或接口有 nothing .

  • 0

    有没有一种方法,如果函数接受参数(tt twoTimeable)我将能够调用tt.result()而不管是否是指向类型的指针,给定result()仅用指针接收器定义 .

    这似乎是一个重大的误解 . 如果 tt 是接口类型 twoTimetable 的变量而不是 result 方法,则可以调用此方法 . 为什么 tt 的基础类型无关紧要 . 接口类型完全封装了基础类型的相关性 . 接口类型提供了一组方法,可以调用这些方法,也不能调用其他方法 .

    具体类型(例如您的MyInt)可分配性对于类型为2Interfaces的变量的问题是一个不同的问题 . 如果您的具体类型(例如MyInt)恰好具有由接口类型(此处为twoTimetables)定义的所有方法,那么它是可分配的,如果不是,则不可分配 .

    问题"what methods does my concrete type have"是第三个问题 . 这是唯一有点复杂的问题 . 在接收器T上定义的任何方法都是T的方法 . 对于指针类型* T,* T上的方法和T计数上的方法 .

  • 0

    Q1:为什么在值接收器方法上使用指针而不是反之亦然?

    因为语言规范说它很好:https://golang.org/ref/spec#Method_sets

    相应指针类型* T的方法集是使用receiver * T或T声明的所有方法的集合(也就是说,它还包含T的方法集) .

    (规范是这样的一个可能的原因:方便 . )

    对于问题的其余部分:我对你的要求没有任何想法 . do Something 的代码完全没问题 . 您在 tt 上调用 result ,这是实现 result() (int, int) 方法的任何类型 . 这种类型是否是指针类型是没有意义的 . 你从这个方法调用中得到两个 int ,并且可以使用这些整数执行任何操作 .

    (关于"pointer to interface"部分:是的 . 技术上可以做到 ttp *twoTimetable . 但你永远不需要这个 . 从不 . (当然这是谎言,但你需要它的情况是如此罕见和微妙,你真的永远不需要这个初学者,一旦你需要它,你就会知道如何使用它 . )这里有一点要记住:你永远不会做"pointer to interface" . )

相关问题