Go language must support multi return function. Do you know why?

Functions (Methods) in most programming languages can only return one value. This function is also a standard definition in mathematics, such as y = f(x). No matter how complex the following f(x) is, there will always be only one y. However, there are a few programming languages. Functions can return multiple values. Go and Python are such languages. In fact, this method of returning multiple values is a syntax sugar for some programming languages, such as Python. But for go, it's really necessary, so why? Keep looking back!

Now let's look at a calc function that returns four values:

package main
func calc(a int, b int) (int, int, int, int) {
    return a + b, a - b, a * b, a / b
}
func main() {
    a, b, c, d := calc(20, 5)
    println(a, b, c, d)
}

This is a function used to calculate the addition, subtraction, multiplication and division of two integers a and b. the function returns these four values at the same time. The calc function is called in the main function. However, it should be noted that when calling the go function, the number of variables used to receive the function return value must be the same as the number of function return values, otherwise it cannot be compiled, and the error message shown in the following figure will be displayed.

There are two ways to assign the return value of the function to the variable. One is the simplified method of this example. The variable on the left is automatically created through ": =" and initialized with the return value of the function. The second method is normal. var is used to define four variables. You can specify the data type for the variable or omit the data type (go will automatically infer the data type of the variable according to the type of the function return value). The code is as follows:

// Omit variable data type
var a1, b1, c1, d1 = calc(20, 5)
// Specifies the data type of the variable
var a2, b2, c2, d2 int = calc(20, 5)

So far, we have finally understood that the original function of go language returns multiple values, which is to assign these return values to the same number of variables, and the data type and quantity of variables must be exactly the same as the data type and quantity of the function return value, no more or less. But this will bring a very troublesome problem.

The go language has a rule that as long as you define variables in the code, you must use them. If you don't use them, don't define them. According to this provision, if a function returns 20 values due to business needs, it means that when calling this function, 20 variables need to be written continuously on the left side of the assignment statement. My God! Variable names are bad. However, the go language provides us with an easy way. If a return value of a function is useless, it can be replaced by an underscore () to indicate that the return value is ignored. As for the calc function given above, you only need the values of a+b and a-b. you can call the calc function with the following code.

package main
func calc(a int, b int) (int, int, int, int) {
    return a + b, a - b, a * b, a / b
}
func main() {
    var a, b, _, _ = calc(20, 5)  // The values of a * b and a / b are omitted
    println(a, b)
}

Now there is no problem calling multi return function, but there is still a small problem when writing multi return function, that is, if there are many return values of the function, putting all the return values behind the return statement may make a mistake. For example, if the order is wrong, the probability of this error is quite high.

The way to solve this problem in Go language is to name the return value, that is, like function parameters, give each return value a name. In this way, when returning a value, you can directly assign a value to the return value variable. However, you still need to call the return statement, but you can return nothing after the return statement. Now let's improve the previous calc function.

package main
func calc(a int, b int) (sum int, sub int, mul int, div int) {
    sum = a + b
    sub = a - b
    mul = a * b
    div = a / b
    return
}
func main() {
    var a, b, c, d = calc(20, 5)
    println(a, b, c, d)
}

See if this code is very clear. Although there is a little more code, it will never be wrong (unless deliberately).

Of course, even if there is a named return value, the return statement can also return a specific value, but it will overwrite the previous value assigned to the named return value variable. The code is as follows:

package main
func calc(a int, b int) (sum int, sub int, mul int, div int) {
    //return a + b, a - b, a * b, a / b
    sum = a + b
    sub = a - b
    mul = a * b
    div = a / b
    return 2 * sum, 2 * sub, 2 * mul, 2 * div
}
func main() {
    var a, b, c, d = calc(20, 5)
    println(a, b, c, d)
}

We can see that in the calc function, the return statement returns all values in the form of double, and the final output result is 50 30 200 8.

Now let's answer the question raised at the beginning of this article: why do Go language functions need to return multiple values.

Because the go language does not have a try...catch statement, although it can handle exceptions through the defer mechanism, it is not easy to use. Therefore, the usual practice is to return an error through a function (a bit like the way C language handles exceptions. Returning 0 means success, and returning non-0 means failure). If the error is nil, it means that no error has occurred and the return value of the function can be used normally. If the error is not nil, it means that there is an error and further processing is needed.

For this reason, if the function of go language does not support returning multiple values, then if it returns error, it can no longer return other values. Therefore, it is reasonable that go supports multiple return value functions. For example, python language supports try...catch, so multi return function is not necessary. Of course, supporting multi return function will also make the program more concise. Therefore, for Python, multi return function is just icing on the cake, while for go language, multi return function is an ecology in the snow.

Let the calc function return another error. Since the denominator of division cannot be 0, if b is 0, error is returned. The code is as follows:

package main
import "errors"
func calc(a int, b int) (sum int, sub int, mul int, div int, err error) {
    if b == 0 {
        err = errors.New("Error: denominator cannot be 0!")
        return
    }
    sum = a + b
    sub = a - b
    mul = a * b
    div = a / b
    err = nil
    return
}
func main() {
    var a1, b1, c1, d1, err1 = calc(20, 5)
    if err1 == nil {
        println(a1, b1, c1, d1)
    } else {
        println(err1.Error())
    }
    var a2, b2, c2, d2, err2 = calc(20, 0)
    if err2 == nil {
        println(a2, b2, c2, d2)
    } else {
        println(err2.Error())
    }
}

Run the program and output the contents shown in the figure below.

Added by microthick on Tue, 30 Nov 2021 10:11:37 +0200