How to pass interfaces indirectly in golang

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

How to pass interfaces indirectly in golang

问题

我有一个带有方法的包:

func Route(router *mux.Router){
    subrouter := router.PathPrefix(_API).Subrouter()
    subrouter.Path(_FOO).HandlerFunc(foo)
    subrouter.Path(_BAR).HandlerFunc(bar)
}

我想通过在我的包中拥有一个匹配的接口来移除对mux的外部依赖,该接口简单地包含上述使用的所有功能,如下所示:

type Router interface{
    Path(string) Path
    PathPrefix(string) Path
}

type Path interface{
    HandlerFunc(http.HandlerFunc)
    Subrouter() Router
}

func Route(router Router){
    subrouter := router.PathPrefix(_API).Subrouter()
    subrouter.Path(_FOO).HandlerFunc(foo)
    subrouter.Path(_BAR).HandlerFunc(bar)
}

但是当我构建时,我得到错误:

*mux.Router does not implement api.Router (wrong type for Path method)
              have Path(string) *mux.Route
              want Path(string) api.Path

但是我认为接口在Go中是隐式使用的,所以我认为*mux.Route实现了我的Path接口。

英文:

I have a package with a method:

func Route(router *mux.Router){
    subrouter := router.PathPrefix(_API).Subrouter()
    subrouter.Path(_FOO).HandlerFunc(foo)
    subrouter.Path(_BAR).HandlerFunc(bar)
}

and I would like to remove the external dependency of mux by having a matching interface in my package that simple encompasses all the functionality used above, like so:

type Router interface{
    Path(string) Path
    PathPrefix(string) Path
}

type Path interface{
    HandlerFunc(http.HandlerFunc)
    Subrouter() Router
}

func Route(router Router){
    subrouter := router.PathPrefix(_API).Subrouter()
    subrouter.Path(_FOO).HandlerFunc(foo)
    subrouter.Path(_BAR).HandlerFunc(bar)
}

but when I build this I get error:

>*mux.Router does not implement api.Router (wrong type for Path method)
> have Path(string) *mux.Route
> want Path(string) api.Path

but I thought interfaces were implicitly used in golang so I thought that *mux.Route did implement my Path interface.

答案1

得分: 5

我认为在Go语言中,接口是隐式使用的。

在特定情况下,值会被隐式地包装在接口中,比如将实现传递给带有接口参数的函数时:

func X(api.Path) {}

X(&mux.Route{}) // 可行,会隐式转换为api.Path

或者从带有接口返回类型的函数返回实现时:

func Y() api.Path {
    return &mux.Route{} // 可行,会隐式转换为api.Path
}

在你提出的问题中,编译器希望得到一个具有以下签名方法的值:

Path(string) api.Path

但你提供的值具有以下签名方法:

Path(string) *mux.Route

正如你可能已经知道的,Go类型是不变的。形式上来说:

type A interface { Path(string) *mux.Route }

不是

type B interface { Path(string) api.Path }

的子类型。因此,这样做是行不通的。

英文:

> I thought interfaces were implicitly used in golang

Values are wrapped in interfaces implicitly, but only in specific cases like when passing an implementation to a function with an interface argument:

func X(api.Path) {}

X(&mux.Route{}) // works, implicitly converted to api.Path

or when returning an implementation from a function with an interface return type:

func Y() api.Path {
    return &mux.Route{} // works, implicitly converted to api.Path
}

In your question's case the compiler wants a value that has a method with the signature:

Path(string) api.Path

But you're giving it a value with a method with signature:

Path(string) *mux.Route

As you might now, Go types are invariant. Formally:

type A interface { Path(string) *mux.Route }

is not a subtype of

type B interface { Path(string) api.Path }

Therefore this won't work.

huangapple
  • 本文由 发表于 2015年5月29日 19:53:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/30528941.html
匿名

发表评论

匿名网友

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

确定