英文:
Cannot use some type in function call
问题
目前,我有两个文件在两个包中。
#文件somepkg/something.go
package somepkg
// ----------------------------------------------------------------------------
// 接口
// ----------------------------------------------------------------------------
type SomeThing interface {
// 其他一些方法
Handle(handler *Handler)
}
type SomeThingImpl struct {
handlers []Handler
}
type Handler interface {
IncomingCall(request *IncomingRequest)
}
// ----------------------------------------------------------------------------
// SomeThingImpl 实现
// ----------------------------------------------------------------------------
func NewSomeThing() SomeThing {
u := new(SomethingImpl)
// 对 u 进行一些操作
return u
}
func (l *SomeThingImpl) Handle(handler *Handler) {
fmt.Printf("handler: %s", handler)
}
#文件main.go
package main
import (
"fmt"
)
type MyHandler struct {}
func (h *MyHandler) IncomingCall(request *somepkg.IncomingRequest) {
fmt.Printf("Handler!")
}
func main() {
mySomeThing := somepkg.NewSomeThing()
handler := new(MyHandler)
// 到目前为止都可以。
mySomeThing.Handle(handler) // <-- 这里出现了编译错误
}
尝试运行go build
会产生以下编译错误:
{...}\main.go:20: cannot use handler (type *MyHandler) as type *somepkg.Handler in argument to mySomething.Handle:
*somepkg.Handler is pointer to interface, not interface
其中main.go:20
指的是我调用mySomeThing.Handle(handler)
的上一行。
实际上,MyHandler
和somepkg.Handler
都似乎是指针。它们都实现了相同的方法。
为什么编译器不认为这些类型是兼容的?
英文:
Currently, I'm having two files in two packages.
File somepkg/something.go
package somepkg
// ----------------------------------------------------------------------------
// Interfaces
// ----------------------------------------------------------------------------
type SomeThing interface {
// some other methods
Handle(handler *Handler)
}
type SomeThingImpl struct {
handlers []Handler
}
type Handler interface {
IncomingCall(request *IncomingRequest)
}
// ----------------------------------------------------------------------------
// SomeThingImpl implementation
// ----------------------------------------------------------------------------
func NewSomeThing() SomeThing {
u := new(SomethingImpl)
// some more operations with u
return u
}
func (l *SomeThingImpl) Handle(handler *Handler) {
fmt.Printf("handler: %s", handler)
}
File main.go
package main
import (
"fmt"
)
type MyHandler struct {}
func (h *MyHandler) IncomingCall(request *somepkg.IncomingRequest) {
fmt.Printf("Handler!")
}
func main() {
mySomeThing := somepkg.NewSomeThing()
handler := new(MyHandler)
// works so far.
mySomeThing.Handle(handler) // <-- here the compilation error occurs
}
trying to run go build
yields the following compilation error:
{...}\main.go:20: cannot use handler (type *MyHandler) as type *somepkg.Handler in argument to mySomething.Handle:
*somepkg.Handler is pointer to interface, not interface
whereas main.go:20
refers to the line above where I'm calling mySomeThing.Handle(handler)
.
Actually, both MyHandler
and somepkg.Handler
seem to be pointers. Both of them implement the same methods.
Why does the compiler not consider these types to be compatible ?
答案1
得分: 2
你有这个方法:
func (l *SomeThingImpl) Handle(handler *Handler) {
fmt.Printf("handler: %s", handler)
}
定义为接受一个接口指针,这可能不是你想要的。你实际上想要的是让*MyHandler
实现Handler
接口,而不是MyHandler
(或者两者都可以),这样你就可以将你的引用类型传递给该方法。
// 新的方法签名
Handle(handler Handler)
// 我更喜欢的赋值语法
handler := &MyHandler{}
// 完全正常工作
mySomeThing.Handle(handler)
如果你真的想保持方法签名的样子,让你的代码工作,你只需要这样做:mySomeThing.Handle(&handler)
,但我怀疑这是否是你真正想做的。
顺便说一下,在你的代码中,*MyHandler
已经通过这个方法func (h *MyHandler) IncomingCall(request *somepkg.IncomingRequest)
实现了接口,因为它的接收类型是*MyHandler
,而不是func (h MyHandler)
,这样只有MyHandler
实现了Handler
接口。这是Go语言中有关接收器和接口的一些细微差别。
英文:
You have this method;
func (l *SomeThingImpl) Handle(handler *Handler) {
fmt.Printf("handler: %s", handler)
}
Defined to take an interface pointer which is likely not what you want. What you're actually looking for is to have *MyHandler
implement the Handler
interface rather than MyHandler
(or both could) so that you can pass your reference type into the method.
//new method sig
Handle(handler Handler)
// my preferred syntax for assignment here
handler := &MyHandler{}
// works just fine
mySomeThing.Handle(handler)
If you really want to keep the method sig how you have it, to make your code work you just need to do mySomeThing.Handle(&handler)
but I'm doubtful that's actually what you want to do.
btw; In your code *MyHandler
is already implementing the interface due to this method func (h *MyHandler) IncomingCall(request *somepkg.IncomingRequest)
haveing *MyHandler
as the receiving type as apposed to func (h MyHandler)
which would make it so only MyHandler
implements the Handler
interface. Some little Go nuance with recievers and interfaces there.
答案2
得分: 1
永远不要使用指向接口的指针(除非你确切知道为什么要这样做)
为了将其传递给定义的函数,你需要显式地创建*somepkg.Handler
(但实际上不要这样做)
var handler somepkg.Handler = new(MyHandler)
mySomeThing.Handle(&handler)
如果你将Handle
定义为
Handle(handler Handler)
任何满足somepkg.Handler
接口的类型都可以直接传递进来。
英文:
Never use a pointer to an interface (well, unless you know exactly why you would want to do so)
In order to pass that into the defined function, you would need to create the *somepkg.Handler
explicitly (but don't really do this)
var handler somepkg.Handler = new(MyHandler)
mySomeThing.Handle(&handler)
If you define Handle
as
Handle(handler Handler)
any type that satisfies the somepkg.Handler
interface can be passed in directly.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论