我想组成另一种类型的类型,但用假的替换其中一个字段(这是一个接口值)。我得到的问题是正在使用基础字段,所以我似乎无法覆盖该字段。
我在这里演示了这个问题:https://play.golang.org/p/lHGnyjzIS-Y
package main
import (
"fmt"
)
type Printer interface {
Print()
}
type PrinterService struct {}
func (ps PrinterService) Print() { fmt.Println("PrinterService") }
type Service struct {
Client PrinterService
}
func (s Service) PrintViaMethod() { s.Client.Print() }
type FakeService struct {
Service
Client Printer
}
type SomeOtherService struct {}
func (sos SomeOtherService) Print() { fmt.Println("SomeOtherService") }
func main() {
s := FakeService{Client: SomeOtherService{}}
s.PrintViaMethod()
}
为什么打印"PrinterService"
?我希望它能打印"SomeOtherService"
。
感谢。
答案 0 :(得分:5)
按s.PrintViaMethod()
,您正在调用提升的方法FakeService.Service.PrintViaMethod()
,方法接收方将是FakeService.Service
,其类型为Service
,和Service.PrintViaMethod()
来电Service.Client.Print()
,其中Service.Client
的类型为PrinterService
,这就是打印"PrinterService"
的原因。
在Go中有embedding,但没有polymorphism。在结构中嵌入类型时,嵌入类型的方法会被提升,并且将成为嵌入器类型的方法集的一部分。但是当调用这样一个提升的方法时,它会将嵌入值作为接收者,而不是嵌入者。
为了实现你想要的,你必须"覆盖" PrintViaMethod()
方法,为FakeService
类型(FakeService
接收方类型)提供实施方法,并在其中调用FakeService.Client.Print()
。
通过这样做s.PrintViaMethod()
将表示FakeService.PrintViaMethod()
方法,因为它将位于PrintViaMethod()
存在的最浅深度(而不是FakeService.Service.PrintViaMethod()
)。详情请见Spec: Selectors。
例如:
func (fs FakeService) PrintViaMethod() {
fs.Client.Print()
}
然后输出将是(在Go Playground上尝试):
SomeOtherService
更多详细信息,请参阅相关问题和答案:
答案 1 :(得分:4)
为什么打印' PrinterService'?我希望它能够打印出SomeOtherService'。
因为那是您的代码所要做的。 PrintViaMethod
调用s.Client.Print()
,s.Client
是PrinterService
的(零值)实例,输出PrinterService
。
您可能希望在s.Print()
中致电main()
。我根本没有看到你PrintByMethod
功能的任何原因。
答案 2 :(得分:0)
根据Flimzy
,您正在调用打印s.Client.Print()
,其类型PrinterService
已实现为Print()
功能打印PrinterService
的接收方。您还可以将Client
结构中PrinterService
Service
的类型更改为Someother service
package embedded
import (
"fmt"
)
type Printer interface {
Print()
}
type PrinterService struct{}
func (ps PrinterService) Print() { fmt.Println("PrinterService") }
type Service struct {
Client SomeOtherService
}
func (s Service) PrintViaMethod() { s.Client.Print() }
type FakeService struct {
Service
Client Printer
}
type SomeOtherService struct{}
func (sos SomeOtherService) Print() { fmt.Println("SomeOtherService") }
func Call() {
s := FakeService{Client: SomeOtherService{}}
s.PrintViaMethod()
}