Reputation: 11154
I have a package-level function (Frob) that takes a function as an argument. For the function argument, I want to pass in a method (FrobMethod) with a particular struct instance as the receiver (myFrob).
The only way I've found to accomplish this is to use a func literal/closure that captures the target struct. That requires repeating the func signature and arguments, which seems too verbose. Is there a better way?
package main
import "fmt"
func Frob( frobber func( int ) ( string ) ) {
fmt.Printf( "Frob %s\n", frobber( 42 ) )
}
type MyFrob struct {
Prefix string
}
func ( m MyFrob ) FrobMethod( n int ) ( string ) {
return fmt.Sprintf( "%s %d", m.Prefix, n )
}
func main() {
myFrob := MyFrob { Prefix: "Hello" }
// C# allows something like this:
//
//Frob( myFrob.FrobMethod )
Frob( func ( n int ) ( string ) {
return myFrob.FrobMethod( n )
} )
}
...a real-world example of this is HandleFunc in net/http.
Upvotes: 4
Views: 560
Reputation: 11154
As of Go 1.1, the C#-style method reference works:
Frob( myFrob.FrobMethod )
See the Method expressions section of the Go Language Specification.
Upvotes: 1
Reputation: 92559
While Go does allow you to create anonymous function assignments to variables and pass them around, another way to approach this problem is to make use of interfaces.
package main
import "fmt"
type Frobber interface {
Frob(int) string
}
type MyFrob struct {
Prefix string
}
func (m MyFrob) Frob(n int) string {
return fmt.Sprintf("%s %d", m.Prefix, n)
}
func Frob(f Frobber) {
fmt.Printf("Frob %s\n", f.Frob(42))
}
func main() {
myFrob := MyFrob {Prefix: "Hello"}
Frob(myFrob)
}
In an object oriented language, you would be able to just pass a method around, but Go isn't OO. You have to start your brain over from the beginning and not try to write the code like you would in other languages. I have that same problem coming from Python.
By the way, I love Go and am actively trying to improve my skills with it as a tool in my tool belt. In response to @Jeremy in the comments, I am only stating that Go is not OO because its not firmly supported to be such by the Go team, and its more commonly referred to as procedural, and, having a mixture of elements from other languages that are themselves considered to be OO
Upvotes: 1
Reputation:
In my opinion, idiomatic Go should use an interface instead of a function in this case:
package main
import "fmt"
type Frobber interface {
FrobMethod(int) string
}
func Frob(frobber Frobber) {
fmt.Printf("Frob %s\n", frobber.FrobMethod(42))
}
type MyFrob struct {
Prefix string
}
func (m MyFrob) FrobMethod(n int) string {
return fmt.Sprintf("%s %d", m.Prefix, n)
}
func main() {
myFrob := MyFrob{Prefix: "Hello"}
Frob(myFrob)
}
The function HandleFunc
in net/http
is a wrapper for function Handle
which takes an interface argument.
Upvotes: 4