Is it possible to define a nameless function that returns an interface?

Viewed 235

I am trying to understand some Go code online.

var botInterface func(*Server) eintefaces.BotInterface

func SetBotInterface(b func(*Server) einterface.BotInterface){
   botInterface = b 
}

Does anyone know what the code is saying? There is no implementation of the nameless function. From what I can tell is that botInterface is defined as a function that returns a interface. Currently botInterface is nil and that is the only related code.

2 Answers

func(*Server) eintefaces.BotInterface is not a nameless function, it's a function type. It's the type of a function that takes *Server as its argument and returns a value of type eintefaces.BotInterface.

botInterface is an unexported variable. Its type is a function type described above.

The SetBotInterface() exported function gives the possibility to set (assign) a value to the unexported botInterface variable. You have to pass a function value of the same type, and it simply assigns it to the unexported variable (you can't access the unexported variable otherwise).

See a similar example with usage:

var f func(string) io.Writer

func SetF(v func(string) io.Writer) {
    f = v
}

func exampleF(s string) io.Writer {
    fmt.Println("Received:", s)
    return os.Stdout
}

func main() {
    SetF(exampleF)

    w := f("foo")
    w.Write([]byte("bar"))
}

Which outputs (try it on the Go Playground):

Received: foo
bar

It is not anonymous function but function type. This code allows you to assign your own function to an unexported botInterface variable (which you can't directly change from outside) in that package. You pass any function that takes *Server and returns einterface.BotInterface as an argument to SetBotInterface. Argument is then set to botInterface and probably called somewhere in that package.

So somewhere in your package you can do

func MyFunc(s *thatpackage.Server) einterface.BotInterface {
 // your code here...
}

and then later pass it to that package like this:

thatpackage.SetBotInterface(MyFunc)

// or even passing anonymous function directly:
thatpackage.SetBotInterface(func (s *thatpackage.Server) einterface.BotInterface {
  // your code here...
})

Note: I referred to package containing SetBotInterface as thatpackage because name is not known from your question.

This approach is often used to implement various customizable handlers in frameworks, etc.

You can think of code you posted like this - it makes it easier to understand what happens there:

type BotInterfaceFuncType = func(*Server) eintefaces.BotInterface 

var botInterface BotInterfaceFuncType

func SetBotInterface(b BotInterfaceFuncType){
   botInterface = b 
}
Related