英文:
Why can't I assign a *Struct to an *Interface?
问题
我只是在通过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
英文:
I'm just working through the Go tour, and I'm confused about pointers and interfaces. Why doesn't this Go code compile?
package main
type Interface interface {}
type Struct struct {}
func main() {
var ps *Struct
var pi *Interface
pi = ps
_, _ = pi, ps
}
i.e. if Struct
is an Interface
, why wouldn't a *Struct
be a *Interface
?
The error message I get is:
prog.go:10: cannot use ps (type *Struct) as type *Interface in assignment:
*Interface is pointer to interface, not interface
答案1
得分: 223
当你有一个实现接口的结构体时,指向该结构体的指针也会自动实现该接口。这就是为什么在函数的原型中从不使用*SomeInterface
,因为这对SomeInterface
没有任何增加,并且在变量声明中也不需要这样的类型(参见这个相关问题)。
接口值不是具体结构体的值(因为它具有可变大小,这是不可能的),而是一种指针(更准确地说是指向结构体和类型的指针)。Russ Cox在这里描述得非常准确:
> 接口值表示为一个两个字的对,其中一个字是指向存储在接口中的类型信息的指针,另一个字是指向关联数据的指针。
这就是为什么Interface
而不是*Interface
是持有实现Interface
的结构体的指针的正确类型。
所以你只需要使用
var pi Interface
英文:
When you have a struct implementing an interface, a pointer to that struct implements automatically that interface too. That's why you never have *SomeInterface
in the prototype of functions, as this wouldn't add anything to SomeInterface
, and you don't need such a type in variable declaration (see this related question).
An interface value isn't the value of the concrete struct (as it has a variable size, this wouldn't be possible), but it's a kind of pointer (to be more precise a pointer to the struct and a pointer to the type). Russ Cox describes it exactly here :
> Interface values are represented as a two-word pair giving a pointer
> to information about the type stored in the interface and a pointer to
> the associated data.
This is why Interface
, and not *Interface
is the correct type to hold a pointer to a struct implementing Interface
.
So you must simply use
var pi Interface
答案2
得分: 10
这可能是你的意思:
package main
type Interface interface{}
type Struct struct{}
func main() {
var ps *Struct
var pi *Interface
pi = new(Interface)
*pi = ps
_, _ = pi, ps
}
编译正常。另请参见这里。
英文:
This is perhaps what you meant:
package main
type Interface interface{}
type Struct struct{}
func main() {
var ps *Struct
var pi *Interface
pi = new(Interface)
*pi = ps
_, _ = pi, ps
}
Compiles OK. See also here.
答案3
得分: 0
这是一种非常简单的将结构体分配给接口的方法:
package main
type Interface interface{}
type Struct struct{}
func main() {
ps := new(Struct)
pi := Interface(ps)
_, _ = pi, ps
}
https://play.golang.org/p/BRTaTA5AG0S
英文:
Here's a very simple way of assigning a struct to an interface:
package main
type Interface interface{}
type Struct struct{}
func main() {
ps := new(Struct)
pi := Interface(ps)
_, _ = pi, ps
}
答案4
得分: 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
文件的Create函数中
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只消耗Events []interface{}
,但实际上我发送的是一个结构体指针,它可以正常工作。
另一个更多的例子在这里
英文:
Im using the following way of interface{}
while im just consuming eventsI interface{}
as arguments, im still able to send a Struct Pointers as you can see below.
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)
Now inside storyboard.go
file Create function
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
}
As you can see above the Storyboard.go is consuming just Events []interface{}
but in-fact Im sending is a Struct pointer and it works fine.
another more example here
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论