If you know the type you're returning, would you still use output arguments?

Viewed 60

A lot of Go code uses the following pattern:

var foo Foo
err := db.LoadFooByID(id, &foo)
// use the loaded foo

This pattern has its merits, especially, when it comes to a type you don't know in advance (interface{}). However, if you already know the type, it any other language, you would use LoadFooByID like this:

foo, err := db.LoadFooByID(id)
// use the loaded foo

And yet, people still prefer the former pattern.

I know that the question is very subjective, but if you had to provide a generic case solution that you apply consistently across your code base (for known types), which one would you go for?

1 Answers

In the first form that takes a pointer, that gives you the possibility to reuse an existing Foo variable, preventing you from generating "garbage". It doesn't matter for a single Foo, but if you're loading Foos in a loop, it might make a difference: you may use a single Foo variable in all iterations.

If you have the first form, you can always create a helper function that provides the functionality of the second form:

func loadFooById(id int) (*Foo, error) {
    var foo Foo
    err := db.LoadFooByID(id, &foo)
    return &foo, err
}

If you have the second form, you can't "convert" it to the first: if the LoadFooByID() function is the one allocating a new Foo, you can't make it reuse an existing one.

Related