Go allows you to have a function that returns multiple values. A function definition that returns three values would be defined similar to:
Since there is more than one return value, it is necessary to enclose it within parentheses. To return values from a function such as the above, you would have a
And we can accept it from within the calling code with an assignment operator as:
If you had lesser number of values in the return statement than is defined in the function signature, then you will see a
In the definition of the function, it is also possible to name each of the return values. We shall see the usage of it later, but the definition would be similar to:
In the following program, we implement our own version of square root of a number. Since square root of a negative number is invalid, we return an error in that case. The return value is then checked in the calling program before continuing the program. In the code below, we have expanded the error handling and repeated it for the purpose of illustration, but of course, it could be modularized.
The return variables that you name in the function signature automatically are zero-ed. This means to say that they have their default initialization values - numbers like integers are floats are set to 0, strings are empty, etc. Structs similarly are zero-ed based on its constituent fields.
Do remember that you can explicitly change the values that are returned. If you specify a different
func SumProdDiff(i, j int) (int, int, int)
Since there is more than one return value, it is necessary to enclose it within parentheses. To return values from a function such as the above, you would have a
return
statement with three comma separated values.return sum, prod, diff
And we can accept it from within the calling code with an assignment operator as:
s, p, d := SumProdDiff(value1, value2)
If you had lesser number of values in the return statement than is defined in the function signature, then you will see a
not enough arguments to return
error. In the definition of the function, it is also possible to name each of the return values. We shall see the usage of it later, but the definition would be similar to:
func SumProdDiff(i, j int) (s int, p int, d int)
Multiple return values
We’ll implement the above example in code. To the method we pass two integers and we expect to get back the sum, product, and difference of the two.Full program
package main import ( "fmt" ) func SumProductDiff(i, j int) (int, int, int) { return i+j, i*j, i-j } func main() { sum, prod, diff := SumProductDiff(3,4) fmt.Println("Sum:", sum, "| Product:",prod, "| Diff:", diff) }
Sum: 7 | Product: 12 | Diff: -1
Multiple return values and error handling
Multiple return values gives us a different way of checking for errors. The typical paradigm is:Partial code
retValue, err := my_function() if err == nil { //go ahead with normal code } else { //error handling code }
In the following program, we implement our own version of square root of a number. Since square root of a negative number is invalid, we return an error in that case. The return value is then checked in the calling program before continuing the program. In the code below, we have expanded the error handling and repeated it for the purpose of illustration, but of course, it could be modularized.
Full program
package main import ( "fmt" "errors" "math" ) func MySqrt(f float64) (float64, error) { //return an error as second parameter if invalid input if (f < 0) { return float64(math.NaN()), errors.New("I won't be able to do a sqrt of negative number!") } //otherwise use default square root function return math.Sqrt(f), nil } func main() { fmt.Print("First example with -1: ") ret1, err1 := MySqrt(-1) if err1 != nil { fmt.Println("Error! Return values are", ret1, err1) } else { fmt.Println("It's ok! Return values are", ret1, err1) } fmt.Print("Second example with 5: ") //you could also write it like this if ret2, err2 := MySqrt(5); err2 != nil { fmt.Println("Error! Return values are", ret2, err2) } else { fmt.Println("It's ok! Return values are", ret2, err2) } }
First example with -1: Error! Return values are NaN I won't be able to do a sqrt of negative number!
Second example with 5: It's ok! Return values are 2.23606797749979
Second example with 5: It's ok! Return values are 2.23606797749979
Named return variables in function definition
Go allows you to name the return variables in the function signature. This allows you to use those variable names itself within your code. When you later have areturn
statement, it is not necessary to mention the variable names as Go automatically knows that the named return variables are the ones to be sent back. As of now, the last return statement still needs to be written, and the compiler will throw an error if you don’t.The return variables that you name in the function signature automatically are zero-ed. This means to say that they have their default initialization values - numbers like integers are floats are set to 0, strings are empty, etc. Structs similarly are zero-ed based on its constituent fields.
Full program
package main import ( "fmt" "errors" "math" ) //name the return variables - by default it will have 'zero-ed' values i.e. numbers are 0, string is empty, etc. func MySqrt2(f float64) (ret float64, err error) { if (f < 0) { //then you can use those variables in code ret = float64(math.NaN()) err = errors.New("I won't be able to do a sqrt of negative number!") } else { ret = math.Sqrt(f) //err is not assigned, so it gets default value nil } //automatically return the named return variables ret and err return } func main() { fmt.Println(MySqrt2(5)) }
2.23606797749979 <nil>
Do remember that you can explicitly change the values that are returned. If you specify a different
return
statement, like say return 5, nil
, then the named variable is ignored and the explicitly returned values are what is sent back.
Partial code
ReplyDeleteretValue, err := my_function()
if err != nil { //go ahead with normal code
} else { //error handling code
}
This should be the other way around, like:
if err != nil { //error handling code
} else { //go ahead with normal code
}
Thank you Ivo, I've updated the check with "if err == nil" to give the same result as you pointed out.
ReplyDeleteHi Sathish dont you think it is redundant to use this :
Deleteif err == nil {
}else{
}
Instead all you need is
if err {//Error code
}else{// Else normal code
}
Hi,
ReplyDeleteFirst, thanks for this great tutorial. I had some problems with the error handling on the sqrt example. I think the MySqrt func needs to look like :
import ..
errors
func MySqrt(f float64) (float64, error) {
if (f<0) {
return float64(math.Nan()), errors.New("Cant ...")
}
return math.Sqrt(f), nil
Eclipse Go plugin was giving me compilation errors with os.NewError and I couldn't find it in the documentation here :
http://golang.org/pkg/os/
Thanks again.
Pete
Thank you Peter. I checked it based on your feedback and have updated it.
DeleteOut of curiosity, can you do this: `foo (bar ())` where
ReplyDeletefoo := func (a int, b error)
and
bar := func () (a int, b error)
?
Yes, actually. I'm still deciding whether or not that's a terrible, terrible thing though.
DeleteThis is really cool! Nesting functions in functions, you can even go another step futher...
DeleteWhat would be the best thing to do error handling, throwing it up to the main function or declare a err variable and do callbacks? :D
sorry, but when exactly did the time for improving Golang pass?
ReplyDeletePerhaps "logical" is not the best word, but rather "pragmatic" in that it is reasonable to expect the binding of arguments to return values to work consistently no matter the location of the arguments in the function's signature.
PHP Training in Chennai |
Pega Training in Chennai
Greens Technology's the leading software Training & placement centre Chennai & ( Adyar)
ReplyDeleteManual Testing training in chennai
Thanks for your informative article.
ReplyDeleteLoadrunner training in chennai
Great Articles nice blog thanks for sharing keep on updating more -
ReplyDeleteBest Hibernate Training in Chennai
Struts Training in Chennai
Best Spring Training in Chennai