golang:“ func()接口{}”和“ func()* MyStruct”不兼容的类型如何?

Suppose I have code, where a function accepts another one as an argument:

type Person struct {
    Name string
}

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

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

func doStuff(){
    printRetrievedItem(personBuilder);
}

This results in error cannot use personBuilder (type func() *Person) as type func() interface {} in function argument. If I change personBuilder return type to interface{}, it works, but in real project I'm working on I want to have a concrete type for clear design and TDD purposes.

Does Go support such method signature generalization? What are the workarounds, if you could not change the personBuilder part (e.g. you have a lot parameterless functions that return different type of struct, and you want to build a consumer function that accepts any of those builders as argument)?

You can use pkg reflect for this. (Note however that the solution of @OneOfOne is more idiomatic).

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's an example in the playground.

One workaround is to define an inline function that calls personBuilder.

printRetrievedItem(func() interface{} {return personBuilder()});

Playground

Either do a wrapper like @GrzegorzŻur suggested or define your own interface and make your xxxxBuilder return it:

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())
}

You can create an interface with a method that returns an 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);
}

This is just an example, please use a better name!

To answer your question, fun() A is not a func() interface{}, for the same reason that []A is not an []interface{}. It's explained very well in the go wiki.