为什么不能将* Struct分配给* Interface?


142

我只是在Go导游中工作,我对指针和接口感到困惑。为什么此Go代码无法编译?

package main

type Interface interface {}

type Struct struct {}

func main() {
    var ps *Struct
    var pi *Interface
    pi = ps

    _, _ = pi, ps
}

即如果Struct是一个Interface,为什么不*Struct成为一个*Interface

我收到的错误消息是:

prog.go:10: cannot use ps (type *Struct) as type *Interface in assignment:
        *Interface is pointer to interface, not interface


看起来接口的行为就像隐式指针一样……
Victor

我可以建议您用它来丰富您的游乐场func main() { var ps *Struct = new(Struct) var pi *Interface var i Interface i = ps pi = &i fmt.Printf("%v, %v, %v\n", *ps, pi, &i) i = *ps fmt.Printf("%v, %v, %v\n", *ps, pi, i) _, _, _ = i, pi, ps }并做出自己的
Victor

Answers:


183

当您有一个实现接口的结构时,指向该结构的指针也会自动实现该接口。这就是为什么您永远都不会拥有*SomeInterface函数原型的原因,因为这不会为添加任何内容SomeInterface,并且您不需要在变量声明中使用这种类型(请参阅此相关问题)。

接口值不是具体结构的值(因为它的大小可变,所以不可能),但是它是一种指针(更精确地说,是指向结构的指针和指向类型的指针)。拉斯·考克斯(Russ Cox)正是在这里描述它:

接口值表示为两个单词对,它给出一个指向有关接口中存储的类型的信息的指针和一个指向关联数据的指针。

在此处输入图片说明

这就是为什么Interface,而不是*Interface容纳指向实现的指针的正确类型Interface

所以你必须简单地使用

var pi Interface

8
好吧,我认为这对我来说很有意义。我只是想知道为什么(在那种情况下),这不仅仅是一个编译时错误var pi *Interface
西蒙·尼克森

1
我进入更多细节来解释它。参见编辑。我建议阅读我链接的Russ Cox的文章。
DenysSéguret2012年

1
这以一种我从未在C或C ++中无法做到的方式帮助我理解了指针...非常感谢您这种优雅而简单的解释:-)
mindplay.dk 2013年

2
好吧,我仍然不明白为什么*SomeInterface不只是一个编译错误?
sazary '16

2
@charneykaye您在这里并不完全正确。在声明接口变量作为函数声明的一部分返回接口类型时,您永远不会拥有* SomeInterface 。但是,您可以在函数的参数中包含* SomeInterface
arauter

7

这也许就是你的意思:

package main

type Interface interface{}

type Struct struct{}

func main() {
        var ps *Struct
        var pi *Interface
        pi = new(Interface)
        *pi = ps

        _, _ = pi, ps
}

编译确定。另请参阅此处


这应该被接受,另一个并不能真正回答问题。
DrKey


0

我使用以下方式,interface{}虽然我只是将其eventsI interface{}用作参数,但仍然可以发送结构指针,如下所示。

func Wait(seconds float64) *WaitEvent {
    return WaitEventCreate(seconds)
}

main.go

var introScene = []interface{}{
        storyboard.Wait(5),
        storyboard.Wait(2),
    }

    var storyboardI = storyboard.Create(stack, introScene)
    stack.Push(&storyboardI)

现在在storyboard.go文件创建功能内

type Storyboard struct {
    Stack  *gui.StateStack
    Events []interface{} //always keep as last args
}

func Create(stack *gui.StateStack, eventsI interface{}) Storyboard {
    sb := Storyboard{
        Stack: stack,
    }

    if eventsI != nil {
        events := reflect.ValueOf(eventsI)
        if events.Len() > 0 {
            sb.Events = make([]interface{}, events.Len())
            for i := 0; i < events.Len(); i++ {
                sb.Events[i] = events.Index(i).Interface()
            }
        }
    }

    return sb
}

正如您在Storyboard.go上方看到的那样,go只是Events []interface{}在消耗,但实际上,即时消息发送是Struct指针,并且工作正常。

这里还有另一个例子

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.