Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass a method reference in Go, like in Java?

Tags:

generics

go

I'm rewriting my app from Java to Go, I know the languages are completely different along with paradigms but still I managed to convert nearly everything.

Unfortunately I'm having trouble passing a generic function as an argument to another function. In Java it looks like this:

I have an interface:

public interface Parser<T> {
    public T parse(String line);
}

Then I use this interface in a generic fetch method

public static <T> List<T> fetch(Parser<T> parser) {
    ...
    parser.parse(someLine);
    ...
    return the list of generic types
}

Then a parser method looks like this:

class Parser{
    static Foo ParseFoo(String line){
        ...
        some custom parsing
        ...
    }
}

And I use it like this:

List<Foo> list = fetch(Parser::ParseFoo);

How do I achieve this in Go?

I've tried declaring generic interfaces, generic functions but I can't wrap my head around this.

like image 959
Jacob Avatar asked Aug 04 '26 19:08

Jacob


1 Answers

An equivalent generic Parser interface would look like this:

type Parser[T any] interface {
    Parse(line string) T
}

Any type with a Parse(string) S method will implicitly satisfy the Parser[S] interface. For example, the following type Foo satisfies Parser[int]:

type Foo struct{}

func (f Foo) Parse(string) int {
    return 0
}

Then, with the generic Parser interface, you can implement your generic Fetch function:

func Fetch[T any](parser Parser[T]) []T {
    panic("not implemented")
}

Passing values that satisfy interfaces

How would you then do in Go the equivalent of passing Java static method like ParseFoo() below?

class Parser {
    static Foo ParseFoo(String line) {
      ...
    }
}

In Go, there are no static methods. Functions can be attached to types, in which case they become methods. As such, for the cases when you would have a static method in Java, you would normally end up with a non-method function or standalone function in Go:

func ParseFoo(line string) Foo {
    ...
}

To make this function satisfy the Parser[Foo] interface, you can define the following ParserFunc adapter:

type ParserFunc[T any] func(string) T

func (f ParserFunc[T]) Parse(line string) T {
    return f(line)
}

This way, from the standalone function ParseFoo – which isn't attached to any type – you can create a value of ParserFunc[Foo], which does satisfy Parser[Foo], and will just call ParseFoo when its Parse method is called:

f := ParserFunc[Foo](ParseFoo)

Finally, you can pass this f value to fetch since f satisfies Parser[Foo]:

fetch[Foo](f)

Note that you need to specify the type argument Foo to fetch as the compiler cannot infer it.


If you really need a method (i.e., like a non-static/instance method in Java), then you may want to look at method values. The procedure will be similar to the one exposed here.

like image 174
ネロク・ゴ Avatar answered Aug 07 '26 17:08

ネロク・ゴ



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!