Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty interface{} in function type

An object of any type can be assigned to an empty interface. For example, we have the following function

func Println(i interface{} ) {
  fmt.Println(i)
}

We can call it by

Println(3)
Println(1.5)
Println("Hello")

But I can't achieve the same thing for function type

func Map(fn func( interface{} )) {  
  ......  
}  

I cannot call this with
Map( func( i int) {......} )
because the type func(int) is different from the type func( interface{} ).

But when I define func( interface{} ), I really mean any type of the input parameters. How can I achieve this in Go?

like image 952
Yiqun Hu Avatar asked Oct 01 '14 06:10

Yiqun Hu


People also ask

What is an empty interface?

Here is a good definition of the empty interface by Jordan Oreilli: An interface is two things: it is a set of methods, but it is also a type. The interface {} type is the interface that has no methods.

What is an empty interface in Golang?

In Go, we can also create interfaces without any methods, known as empty interfaces. For example, Here, we have created an empty interface without any methods. In Go, we can create variables of the empty interface type. For example,

What is an interface with no methods?

The interface {} type is the interface that has no methods. Since there is no implements keyword, all types implement at least zero methods, and satisfying an interface is done automatically, all types satisfy the empty interface

What is the difference between interface and interface type?

The functionality that is described by the interface can be adopted by any type, regardless of where the type appears in the inheritance hierarchy. A type implements an interface by providing implementations for the members of the interface. An empty interface does not define any members.


2 Answers

It fails because the signatures don't match.

When you call Println(3), the function isn't taking an integer as its first argument. Rather the integer gets packed inside an interface{} variable (an automatic conversion, since integers conform to the interface), and that variable is passed to the function. This conversion happens on the calling side, so the process of calling the function is different to calling a function matching func(i int).

If you want to write a function that accepts arbitrary unary functions, you will need to declare it to take an interface{} variable as its argument and then check the value using the reflect package. The reflect package can also help you call arbitrary functions where you don't know the signature at compile time.

For example:

func Map(f, v interface{}) interface{} {
    fn := reflect.ValueOf(f)
    fnType := fn.Type()
    if fnType.Kind() != reflect.Func || fnType.NumIn() != 1 || fnType.NumOut() != 1 {
        panic("Expected a unary function returning a single value")
    }
    res := fn.Call([]reflect.Value{reflect.ValueOf(v)})
    return res[0].Interface()
}

This will call the given function f with the argument v and return the result. Provided v is assignable to f's first argument the call will succeed without a panic. You can experiment with this example here: http://play.golang.org/p/kkBu56JYb8

like image 119
James Henstridge Avatar answered Oct 19 '22 21:10

James Henstridge


I do realise its an old discussion, but came across the post and wanted to play around with the concept of having arbitrary function func (interface{}) within another function, instead of interface{}. I could write a simple implementation, by providing an inline implementation of a function which would accept interface{}. And we can call this function from within another function

varForGenFunc := func(in interface{}) int {                             
                    fmt.Println("type of this object: ",reflect.TypeOf(in))
                    return 1}

TakeGenericFunc(varForGenFunc, variableForGen)

Going by this, we can write any implementations of func(interface{}) and pass it as parameter to TakeGenericFunc

You can play around with it here:

https://play.golang.org/p/f5UUhyhEx7u

like image 31
Akash Mishra Avatar answered Oct 19 '22 20:10

Akash Mishra