在函数调用中无法使用某些类型。

huangapple go评论82阅读模式
英文:

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)的上一行。

实际上,MyHandlersomepkg.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.

huangapple
  • 本文由 发表于 2015年7月15日 00:13:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/31411972.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定