dongshi9719
2015-09-02 06:09
浏览 93
已采纳

在Go中使用空接口返回类型的参数中的accept函数

I'm new to Go and I would like to understand why the code snippet below does not compile. What is the Go way of accepting a function as a function argument that may have any return type?

package main

func main() {
    test(a) // Error: cannot use a (type func() string) as type func() interface {} in argument to test
    test(b) // Error: cannot use b (type func() int) as type func() interface {} in argument to test
}

func a() string {
    return "hello"
}

func b() int {
    return 1
}

func test(x func() interface{}) {

    // some code...
    v := x()
    // some more code....
}

Play: https://play.golang.org/p/CqbuEZGy12

My solution based on Volker's answer:

package main

import (
    "fmt"
)

func main() {

    // Wrap function a and b with an anonymous function
    // that has an empty interface return type. With this
    // anonymous function, the call signature of test
    // can be satisfied without needing to modify the return
    // type of function a and b.

    test(func() interface{} {
        return a()
    })

    test(func() interface{} {
        return b()
    })
}

func a() string {
     return "hello"
}

func b() int {
    return 1
}

func test(x func() interface{}) {
    v := x()
    fmt.Println(v)  
}

Play: https://play.golang.org/p/waOGBZZwN7

图片转代码服务由CSDN问答提供 功能建议

我是Go语言的新手,我想了解为什么下面的代码片段无法编译。 将函数作为可能具有任何返回类型的函数参数接受的Go方法是什么?

  package main 
 
func main(){
 test(a)  //错误:不能将(func()类型的字符串)作为func()接口{}用作test 
 test(b)的参数//错误:不能将b(func()int类型)作为func(  )在测试参数中的接口{} 
} 
 
func a()字符串{
返回“ hello” 
} 
 
func b()int {
返回1 
} 
 
func测试 (x func()interface {}){
 
 //一些代码... 
v:= x()
 //其他代码...... 
} 
   
 
 

播放: https://play.golang.org/p/CqbuEZGy12

我基于Volker答案的解决方案:

 程序包主
 
import(  
“ fmt” 
)
 
func main(){
 
 //使用匿名函数
 //封装函数a和b,该函数的接口返回类型为空。 使用此
 //匿名函数,无需修改函数a和b的return 
 //就可以满足test 
 //的调用签名。
 
 test(func()interface {}  {
 return a()
})
 
 test(func()interface {} {
 return b()
})
} 
 
func a()string {
 return“ 你好“ 
} 
 
func b()int {
 return 1 
} 
 
func test(x func()interface {}){
v:= x()
 fmt.Println(v  )
} 
   
 
 

播放: https ://play.golang.org/p/waOGBZZwN7

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • duangu1033 2015-09-02 06:41
    已采纳

    You tripped over a very common misconception for Go newcomers: The empty interface interface{} does not mean "any type". Really, it does not. Go is statically typed. The empty interface interface {} is an actual (strongly typed type) like e.g. string or struct{Foo int} or interface{Explode() bool}.

    That means if something has the type interface{} it has that type and not "any type".

    Your function

    func test(x func() interface{})
    

    takes one parameter. This parameter is a (parameterless function) which returns a specific type, the type interface{}. You can pass any function to test which matches this signature: "No parameters and return interface{}". None of your functions a and b match this signature.

    As said above: interface {} is not a magical abbreviation for "whatever",it is a distinct static type.

    You have to change e.g. a to:

    func a() interface{} {
        return "hello"
    }
    

    Now this might look strange as you return a string which is not of type interface{}. This works because any type is assignable to variables of type interface{} (as every type has at least no methods :-).

    打赏 评论
  • douxi8759 2015-09-02 06:33

    As the Go specification states:

    A function type denotes the set of all functions with the same parameter and result types

    In your case, your result types differ (string vs interface{})

    To be able to receive a function with any kind of result type, test would have to be defined as:

    func text(x interface{}) { ... }
    

    and then you will have to use reflect package to call the function stored in x.

    Edit

    Such a test function would look like this:

    func test(x interface{}) {
        v := reflect.ValueOf(x)
    
        if v.Kind() != reflect.Func {
            panic("Test requires a function")
        }
    
        t := v.Type()
    
        if t.NumIn() != 0 && t.NumOut() != 1 {
            panic("Function type must have no input parameters and a single return value")
        }
    
        values := v.Call(nil)
    
        val := values[0].Interface()
        // some more code..
    }
    

    Playground: https://play.golang.org/p/trC2lOSLNE

    打赏 评论

相关推荐 更多相似问题