如何在Golang中使用回调函数中的接口?

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

How to use an interface in a callback with Golang?

问题

我正在尝试使用Go语言的Faye客户端,但是当我尝试为客户端创建一个接口时,由于回调函数中的类型问题,似乎出现了错误。

在这一点上,它会出现以下错误:

# command-line-arguments
main/fayetest.go:27: cannot use wray.NewFayeClient("http://localhost/faye") (type *wray.FayeClient) as type Subscriber in argument to subscribeMe:
    *wray.FayeClient does not implement Subscriber (wrong type for Subscribe method)
            have Subscribe(string, bool, func(wray.Message)) (wray.SubscriptionPromise, error)
            want Subscribe(string, bool, func(Message)) (Promise, error)

看起来应该是可以工作的,因为客户端确实满足接口的要求。

作为一个旁白,我是Faye客户端的作者,有什么我可以做的来使其适应接口吗?除了放弃回调函数之外?

英文:

I am trying to use a Faye client for Go but when I try to make an interface for the client it seems to fail due to to the type in the callback:

package main

import (
	"fmt"
	"github.com/autogrowsystems/wray"
)

type Message interface {
	Data() map[string]interface{}
}

type Promise interface {
	Successful() bool
}

type Subscriber interface {
	Subscribe(string, bool, func(Message)) (Promise, error)
}

func subscribeMe(subber Subscriber) {
	subber.Subscribe("/my/chan", false, func(msg Message) {
		fmt.Printf("got data: %+v", msg.Data())
	})
}

func main() {
	subscribeMe(wray.NewFayeClient("http://localhost/faye"))
	fmt.Println("all good!")
}

At that point it fails with the following error:

# command-line-arguments
main/fayetest.go:27: cannot use wray.NewFayeClient("http://localhost/faye") (type *wray.FayeClient) as type Subscriber in argument to subscribeMe:
    *wray.FayeClient does not implement Subscriber (wrong type for Subscribe method)
            have Subscribe(string, bool, func(wray.Message)) (wray.SubscriptionPromise, error)
            want Subscribe(string, bool, func(Message)) (Promise, error)

It seems as though it should work as the client does satisfy the interface:

// wray.go - wray.FayeClient
func (self *FayeClient) Subscribe(channel string, force bool, callback func(Message)) (promise SubscriptionPromise, err error) {
}

// response.go - wray.Message 
func (self Message) Data() map[string]interface{} {
}

// wray.go - wray.SubscriptionPromise
func (self SubscriptionPromise) Successful() bool {
}

It should work right? Or does the callback mess up the satisfaction of the interface?

Edit: as an aside, I am the author of that fork of the Faye Client, is there anything I can do to make it conducive to interfaces? Apart from ditching callbacks?

答案1

得分: 4

FayeClient.Subscribe 实现了以下函数:

Subscribe(string, bool, func(wray.Message)) (wray.SubscriptionPromise, error)

而你的 Subscriber 接口要求的函数是:

Subscribe(string, bool, func(Message)) (Promise, error)

请注意回调函数的参数不同 (Message != wray.MessagePromise != wray.SubscriptionPromise),这就是为什么你的代码无法编译的原因。

你不需要重新声明 MessagePromise 接口,只需使用库中的接口即可。

英文:

FayeClient.Subscribe implements:

Subscribe(string, bool, func(wray.Message)) (wray.SubscriptionPromise, error)

and your interface Subscriber requires the function:

Subscribe(string, bool, func(Message)) (Promise, error)

Notice the different parameters of the callback function (Message != wray.Message, Promise != wray.SubscriptionPromise), and that's why your code won't compile.

You don't need to declare the interfaces Message and Promise again, just use the ones from the library.

答案2

得分: 0

尽管你声称wray.FayeClient实现了你的Subscriber接口,但它的Subscribe方法与接口中定义的方法具有不同的签名。

Subscribe(string, bool, func(wray.Message)) (wray.SubscriptionPromise, error)Subscribe(string, bool, func(Message)) (Promise, error)并不是同一回事。wray.Message可能实现了Message接口,但它仍然是不同的类型wray.SubscriptionPromisePromise也是如此。

如果你想使你的库更适合接口,你需要修改库本身,使其接受接口参数并返回接口,而不是具体类型。

英文:

Despite what you claim, wray.FayeClient doesn't implement your Subscriber interface, because it's Subscribe method has a different signature from the one defined in your interface.

Subscribe(string, bool, func(wray.Message)) (wray.SubscriptionPromise, error) simply is not the same thing as Subscribe(string, bool, func(Message)) (Promise, error). wray.Message may implement Message, but it's still a different type. Same goes for wray.SubscriptionPromise and Promise.

If you want to make your library more conducive to interfaces, you need to change the library itself to accept interface arguments and return interfaces instead of concrete types.

huangapple
  • 本文由 发表于 2016年3月2日 04:38:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/35733002.html
匿名

发表评论

匿名网友

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

确定