Naming receiving variables from a multiple return function - go

Go allows for multiple named return values, but what about the receiving variables? Are they protected when return values are juggled around?
Let's say we start with this:
func foo() (i int, j int) {
i = 1
j = 2
return
}
a, b := foo()
Now what if some other coder comes by and makes the following change to foo's definition:
func foo() (j int, i int) {
my calling function is invalidated. Is it, then, possible to name the returned values from the calling side as well. For instance, if I called it like this:
(a:i, b:j) := foo()
then I would be attaching them to the named return values, rather than assigning them in the order they are returned.
So, is there a way to solve that problem?

This is no different than rearranging the input parameters. As a rule, don't do that unless you intend to make a breaking change. But if you want to deal with things by name rather than position, you want a struct. For example, you can use anonymous structs:
func foo() struct {
i int
j int
} {
return struct {
i int
j int
}{1, 2}
}
func main() {
result := foo()
fmt.Println(result.i, result.j)
}
Of course you can also name the struct if you used it in other places, but there's no need if you just want to name the fields.

Related

Go - The difference between var and func to define a function

I'm coming from an Scala background, and in Scala, you could define functions both as a single value, or an actual function, for instance:
val inc1: Int => Int = _ + 1 // single FUNCTION value
def inc2(x: Int): Int = x + 1 // normal function definition
// in this case "inc1 eq inc1" is true, since this is a single instance
// but "inc2 eq inc2" is false
And these 2 have some differences (i.e., size allocation, first one is a single instance, while the other one returns an instance each time it is invoked, ...), so based on the use case, we could kind of reason which one to use. Now I'm new to golang, and wanted to know if the below 2 function definitions (correct me if I'm wrong with the phrase) differ in Golang, and if so, what are differences?
var inc1 = func(x int) int { return x + 1 }
func inc2(x int) int { return x + 1 }
Thanks in advance!
Scala borrows a lot from functional programming. Go does not.
(If you've used multiple other programming languages, you should definitely read the Go specification. It's not very long as Go is not a very large language, although the new generics definitely complicate things a bit.)
In Go, the func keyword introduces a function definition or function type, with the details being context-dependent. The var keyword introduces a variable declaration.1 So:
func inc2(x int) int { return x + 1 }
defines a function, inc2, whose code is as shown. But:
var inc1 = // ...
declares and then initializes a variable, inc1. The type and initial value of the variable are determined by the commented-out section, so:
var inc1 = func(x int) int { return x + 1 }
defines a function (with no name) whose code is as shown. That function is then assigned to the variable as its initial value, so that the implied type of the variable is func (int) int or function taking one argument of type int and returning one value of type int.
Having created a variable, you can now either call the function currently stored in that variable:
func callit(arg int) {
result := inc1(arg)
// ... do something with the result ...
}
Or you can assign a new value into the variable, e.g.:
func overwrite() {
inc1 = func(a int) int { return a * 2 } // name `inc1` is now misleading
}
Because inc2 is a function, you can't re-assign a new value to it: it's just a function, not a variable.
1Note that a variable declaration with an initialization can use the "short declaration" form:
func f() {
v := 3
// ...
}
where we leave out the type and just say "use the type of the expression to figure out the type of the declaration". This declares and initializes the variable. Short declarations can only appear in block scope, so these must be inside some function. Other than omitting the var keyword they do nothing that you couldn't do by including the var keyword, or sometimes multiple var keywords:
result, err := doit()
might require:
var result someType
var err error
result, err = doit()
when written without using the short-declaration form.

Is it possible to define an anonymous interface implementation in Go?

Consider some given interface and a function of an imaginary library that uses it like
// Binary and Ternary operation on ints
type NumOp interface {
Binary(int, int) int
Ternary(int, int, int) int
}
func RandomNumOp(op NumOp) {
var (
a = rand.Intn(100) - 50
b = rand.Intn(100) - 50
c = rand.Intn(100) - 50
)
fmt.Printf("%d <op> %d = %d\n", a, b, op.Binary(a,b))
fmt.Printf("%d <op> %d <op> %d = %d\n", a, b, c, op.Ternary(a,b,c))
}
A possible type implementing that interface could be
// MyAdd defines additions on 2 or 3 int variables
type MyAdd struct {}
func (MyAdd) Binary(a, b int) int {return a + b }
func (MyAdd) Ternary(a, b, c int) int {return a + b + c }
I am dealing with many different interfaces defining a few functions that in some cases need to be implemented using functions mostly working as NOP-like operations, do not rely on any struct member and are only used in a single position in the project (no reusability needed).
Is there a simpler (less verbose) way in Go to define a (preferably) anonymous implementation of an interface using anonymous functions, just like (pseudo code, I know it's not working that way):
RandomNumOp({
Binary: func(a,b int) int { return a+b},
Ternary: func(a,b,c int) int {return a+b+c},
})
If implementation must work
If the value implementing the interface must work (e.g. its methods must be callable without panic), then you can't do it.
Method declarations must be at the top level (file level). And to implement an interface that has more than 0 methods, that requires to have the method declarations somewhere.
Sure, you can use a struct and embed an existing implementation, but then again, it requires to already have an existing implementation, whose methods must already be defined "somewhere": at the file level.
If you need a "dummy" but workable implementation, them use / pass any implementation, e.g. a value of your MyAdd type. If you want to stress that the implementation doesn't matter, then create a dummy implementation whose name indicates that:
type DummyOp struct{}
func (DummyOp) Binary(_, _ int) int { return 0 }
func (DummyOp) Ternary(_, _, _ int) int { return 0 }
If you need to supply implementation for some of the methods dynamically, you may create a delegator struct type which holds functions for the methods, and the actual methods check if the respective function is set, in which case it is called, else nothing will be done.
This is how it could look like:
type CustomOp struct {
binary func(int, int) int
ternary func(int, int, int) int
}
func (cop CustomOp) Binary(a, b int) int {
if cop.binary != nil {
return cop.binary(a, b)
}
return 0
}
func (cop CustomOp) Ternary(a, b, c int) int {
if cop.ternary != nil {
return cop.ternary(a, b, c)
}
return 0
}
When using it, you have the freedom to only supply a subset of functions, the rest will be a no-op:
RandomNumOp(CustomOp{
binary: func(a, b int) int { return a + b },
})
If implementation is not required to work
If you only need a value that implements an interface but you don't require its methods to be "callable" (to not panic if called), you may simply use an anonymous struct literal, embedding the interface type:
var op NumOp = struct{ NumOp }{}

Return only the first result of a multiple return values in golang

Absolute newbie question here.
Some functions in Go return more than one value (normally, the value and an error). I was writing a func who return the return value of one of those functions, and even if it is very easy to put the values on variables and return only the first one, I have the doubt if I could do the same in only one line without the extra variable. This is something often uses in other languages like C, Java, C#, Ruby, etc
func someFunc (param string) int {
// do something with the string, not very important
return strconv.Atoi(param)
}
I know this works
func someFunc (param string) int {
// do something with the string, not very important
var result int
result, _ = strconv.Atoi(param)
return result
}
It is this possible in Go? It is considered a "good practice" (like in Java*)
Note: Before someone say that this technique is not a good practice in Java, clarify that is not important for the question, but some people (like the ones in the company I work) encourage that style.
Use a short variable declaration for the shortest code to accomplish this goal:
func SomeFunc(parm string) int {
result, _ := strconv.Atoi(param)
return result
}
There is no one line solution without introducing a helper function that accepts two arguments and returns the first. One of these helper functions would be needed for each combination of types where you want to ignore a value.
Your best possible one-liner is a helper function written as:
func first(n int, _ error) int {
return n
}
func SomeFunc(param string) int {
return first(strconv.Atoi(param))
}
Note that:
the argument types and positions must match exactly
the second argument to first has the blank identifier (_), making it clear that you wish to completely ignore it. [1]
If you absolutely don't want to declare a named function, you may use a function literal, but that looks real ugly:
func SomeFunc(param string) int {
return func(n int, _ error) int { return n }(strconv.Atoi(param))
}
In general, the helper function is worth it if you have a lot of repetition in your code. Otherwise just use a temp variable, which looks clean and idiomatic:
func SomeFunc(param string) int {
n, _ := strconv.Atoi(param)
return n
}
Playground: https://play.golang.org/p/X8EOh_JVDDG
Once generics will be added to the language in Go 1.18, you will be able to write a helper function that can be used with any return pair and preserve type safety on the first one:
func first[T, U any](val T, _ U) T {
return val
}
func SomeFunc(param string) int {
return first(strconv.Atoi(param))
}
Go2 Playground: https://go2goplay.golang.org/p/vLmTuwzrl5o
Footnotes:
[1] Keep in mind that in case of strings.Atoi the second return value is an error, and ignoring errors is bad practice. However there are cases where the success of the operation truly doesn't matter, then it's fine to use _ to ignore the argument.

Creating objects in Go

I'm playing around with Go for the first time. Consider this example.
type Foo struct {
Id int
}
func createFoo(id int) Foo {
return Foo{id}
}
This is perfectly fine for small objects, but how to create factory function for big objects?
In that case it's better to return pointer to avoid copying large chunks of data.
// now Foo has a lot of fields
func createFoo(id int /* other data here */) *Foo {
x := doSomeCalc()
return &Foo{
Id: id
//X: x and other data
}
}
or
func createFoo(id int /* other data here */) *Foo {
x := doSomeCalc()
f := new(Foo)
f.Id = id
//f.X = x and other data
return f
}
What's the difference between these two? What's the canonical way of doing it?
The convention is to write NewFoo functions to create and initialize objects. Examples:
xml.NewDecoder
http.NewRequest
You can always return pointers if you like since there is no syntactic difference when accessing methods or attributes. I would even go as far and say that it is often more convenient to return pointers so that you can use pointer receiver methods directly on the returned object. Imagine a base like this:
type Foo struct{}
func (f *Foo) M1() {}
When returning the object you cannot do this, since the returned value is not addressable (example on play):
NewFoo().M1()
When returning a pointer, you can do this. (example on play)
There is no difference. Sometimes one version is the "natural one", sometimes the other. Most gophers would prefere the first variant (unless the second has some advantages).
(Nitpick: Foo{id} is bad practice. Use Foo{Id: id} instead.)

How to access individual values from a multi-value returning function?

Go functions can return multiple values:
func f() (int, int) {
return 2, 3
}
Is there any way to access individual values from such a multi-value returning function except assignment, i.e. suppose there is
func g(i int) {...}
is there is simpler way to write the following two lines?
_, i = f()
g(i)
My personal favorite would be g(f()[1]) but that's not possible either.
The current solution used by the standard library is to write simple helper functions which are dropping the unwanted return values. For example, take a look at the template package.
A lot of functions there return a (*Template, os.Error) tuple, but there is a helper called template.Must() which only returns a *Template and panics if the error isn't nil.
Alternatively, a general helper function like func extract(index int, values ...interface{}) interface{} might do the trick. But since there isn't support for generics yet, I wouldn't write something like that.
Use an anonymous struct instead of multiple return values.
func f() (struct{i,j int}) {
return struct{i, j int}{2, 3}
}
func g(i int) { ... }
func main() {
g(f().j)
}
Of course this only works when you are writing the function. Though you can wrap existing ones with this if you want.
g(func(fst,snd int) int { return snd }(f()))
or defined snd
func snd(x, y int) int {
return y
}
g(snd(f()))
or if function return array
func f() ([2]int) {
return [2]int{2, 3}
}
g(f()[1])
There isn't a simpler way.
A possible solution would look for example like this:
g(f().1)
There is no syntactic support for a feature like this one in Go.

Resources