golang:“func()interface {}”和“func()* MyStruct”不兼容类型怎么样?

时间:2015-07-14 12:41:19

标签: go

假设我有代码,其中函数接受另一个作为参数:

type Person struct {
    Name string
}

func personBuilder() * Person {
    return &Person{Name: "John"}
}

func printRetrievedItem(callback func() interface {}){
    fmt.Print(callback());
}

func doStuff(){
    printRetrievedItem(personBuilder);
}

这会导致错误cannot use personBuilder (type func() *Person) as type func() interface {} in function argument。如果我将personBuilder返回类型更改为interface{},它可以正常工作,但在实际项目中我正在研究我希望有一个具体类型用于清晰设计和TDD目的。

Go支持这样的方法签名概括吗?有什么办法,如果你不能改变personBuilder部分(例如,你有很多无参数函数返回不同类型的结构,并且你想构建一个接受任何构造函数作为参数的消费者函数)?

3 个答案:

答案 0 :(得分:3)

要么像@GrzegorzŻur这样的包装器建议或定义您自己的界面并让xxxxBuilder返回它:

type Namer interface {
    Name() string
}

type Person struct {
    name string
}

func (p *Person) Name() string {
    return p.name
}

func personBuilder() Namer {
    return &Person{name: "John"}
}

func printRetrievedItem(callback func() Namer) {
    fmt.Printf("%T: %v", callback(), callback().Name())
}

答案 1 :(得分:3)

您可以使用返回interface{}

的方法创建一个界面
type Thinger interface {
    Thing() interface{}
}

func (p *Person) Thing() interface{} {
    return p
}

func printRetrievedItem(t Thinger){
    fmt.Print(t.Thing());
}

func doStuff(){
    printRetrievedItem(personBuilder);
}

这只是一个例子,请使用更好的名字!

要回答您的问题,fun() A不是func() interface{},原因与[]A不是[]interface{}的原因相同。它在go wiki中得到了很好的解释。

答案 2 :(得分:1)

您可以使用pkg reflect。 (但请注意,@OneOfOne的解决方案更具惯用性。)

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name string
}

func personBuilder() *Person {
    return &Person{Name: "John"}
}

func printRetrievedItem(callback interface{}) {
    vals := reflect.ValueOf(callback).Call([]reflect.Value{})
    fmt.Println(vals[0].Interface())
}

func main() {
    printRetrievedItem(personBuilder) // &{John}
    printRetrievedItem(func() string { return "hello" }) // hello
}

Here是操场上的一个例子。