英文:
In Go can I return a struct that meets an interface without access to that interface?
问题
我认为最好的解释方法是通过示例,所以这里是代码:
package main
import (
"fmt"
)
// Greeter greets with a Greeting.
type Greeter interface {
Greet() Greeting
}
// A Greeting has a string representation.
type Greeting interface {
String() string
}
type Hello struct{}
// Hello greets by returning itself...
func (h *Hello) Greet() Greeting {
return h
}
// ...because Hello also has a string representation.
func (h *Hello) String() string {
return "Hello"
}
// But Go says Hello doesn't implement Greeter.
func main() {
var g interface{} = &Hello{}
g, ok := g.(Greeter)
fmt.Println(ok)
}
这将打印出false
。你可以运行并尝试它:https://play.golang.org/p/A_2k_ku_Q2
在我的实际情况中,结构体Hello
和Greeter
、Greeting
的接口位于不同的包中,它们彼此不导入,我希望保持这种方式。也许我对Go中的接口有些理解上的问题,但是在阅读了这么多相关内容之后,我仍然无法理解其中的关键点。你们有什么指导意见吗?也许对于这个问题还有其他的方法?谢谢!
英文:
I think the best way to explain this is by example, so here it is:
package main
import (
"fmt"
)
// Greeter greets with a Greeting.
type Greeter interface {
Greet() Greeting
}
// A Greeting has a string representation.
type Greeting interface {
String() string
}
type Hello struct {}
// Hello greets by returning itself...
func (h *Hello) Greet() *Hello {
return h
}
// ...because Hello also has a string representation.
func (h *Hello) String() string {
return "Hello"
}
// But Go says Hello doesn't implement Greeter.
func main() {
var g interface{} = &Hello{}
g, ok := g.(Greeter)
fmt.Println(ok)
}
This prints false
. You can run and play with it: https://play.golang.org/p/A_2k_ku_Q2
In my real case the struct Hello
and the interfaces for Greeter
and Greeting
are in different packages that do not import each other and I wanted to keep it that way. I'm perhaps missing some understanding of interfaces in Go but after reading so much about it I still can't put my finger on it. Would you guys have any pointers for me? Maybe another approach for the problem? Thanks!
答案1
得分: 11
根据评论中所述,问题在于一旦你的接口具有以下签名:
type Greeter interface {
Greet() Greeting
}
任何有效的实现都必须将Greeting
作为返回类型。
但是,正如文档所示,你不需要给接口命名:
https://golang.org/ref/spec#Interface_types
为了能够实现你所需的功能,你可以直接在返回值中声明接口,而不给它命名。
// Greeter greets with anything that has a String() method
type Greeter interface {
Greet() interface{ String() string }
}
然后,你的Hello
的Greet()
函数可以这样写:
// Hello greets by returning itself...
func (h *Hello) Greet() interface{ String() string } {
return h
}
在这里可以找到一个修改后的示例代码:
https://play.golang.org/p/HteA_9jFd4
英文:
As stated in the comments, problem here is once your interface has this signature:
type Greeter interface {
Greet() Greeting
}
The any valid implementation must use exactly Greeting
as the return type.
But, as the documentation shows, you don't need to give the interface a name:
https://golang.org/ref/spec#Interface_types
In order to be able to implement what you need, you might declare the interface directly in the return value, without giving it a name.
// Greeter greets with anything that has a String() method
type Greeter interface {
Greet() interface{ String() string }
}
Then your Greet()
function for Hello
can do this:
// Hello greets by returning itself...
func (h *Hello) Greet() interface{ String() string } {
return h
}
Find here a modified playground showing the working example:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论