我正在尝试将一段指针传递给实现接口LogicAdapter的结构。这是我的代码:
main.go:
var adapters[]LogicAdapter
adapter1 := &ExampleAdapter{}
fmt.Printf("Addr: %p\n", adapter1)
adapters = append(adapters, adapter1)
bot := ChatterBot{"Charlie", MultiLogicAdapter{adapters}}
bot.getResponse("test", 0)
multiadapterlogic.go:
type MultiLogicAdapter struct {
adapters []LogicAdapter
}
func (logic *MultiLogicAdapter) process(text string, session int) string {
//response := logic.adapters[0].process(text, session)
response := ""
for _, adapter := range logic.adapters {
fmt.Printf("Addr: %p\n", &adapter)
}
_ = response
return ""
}
main的输出是:
Addr: 0x5178f0
Addr: 0xc42000a340
我没有包含LogicAdapter,因为我不认为这是必要的。
我不喜欢用很多代码来填充它,但是如果它使事情更容易理解,那么这里是ChatterBot(但请记住bot.getResponse
调用process
,就是这样)
chatterbot.go
type ChatterBot struct {
Name string
MultiLogicAdapter
}
func (bot *ChatterBot) getResponse(text string, session int) string {
response := bot.process(text, session)
_ = response
return ""
}
首先,我想到了以这种方式存储指向LogicAdapters的指针
var adapters[]*LogicAdapter
但每当我尝试在那里插入adapter1指针时,我得到了:
* LogicAdapter是指向接口的指针,而不是接口
所以我发现了this并且学会了这个:
当你有一个实现接口的结构时,指向它的指针 struct也自动实现该接口。这就是你的原因 在函数原型中永远不会有* SomeInterface,就像这样 不会向SomeInterface添加任何内容,也不需要这样的类型 在变量声明中(参见此相关问题)。
所以我决定在代码中看到adapters[]
声明。问题是,除adapters
存储指向adapter1
的指针外,当它在MultiLogicAdapter
中打印时,它是另一个地址。我知道我将adapters
作为副本传递给MultiLogicAdapter
,但副本与adapter1
具有相同的引用。那么发生了什么?
为什么我在迭代指针?因此:https://www.goinggo.net/2013/09/iterating-over-slices-in-go.html 如果我不这样做,我将创造许多不必要的副本。
答案 0 :(得分:0)
在var adapters []LogicAdapter
中,您有一系列接口。接口本身本身就是一个对象,它携带指向你分配给它的对象的指针(有一些额外的信息来跟踪它的类型等)。因此,当您向其附加*ExampleAdapter
时,您将创建一个包含指向ExampleAdapter
的指针的接口实例。
稍后,当您执行for _, adapter := range logic.adapters {...}
时,循环中声明的变量adapter
将是切片中“对象”接口的副本。因此,当您使用&adapter
获取指针时,您会获得指向接口的指针,而不是指向ExampleAdapter
接口包含指针的指针。
有关接口内部的更详细说明,请参阅示例https://research.swtch.com/interfaces。