Wednesday, June 15, 2011

Multiple return values from Go functions

Go allows you to have a function that returns multiple values. A function definition that returns three values would be defined similar to:

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

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 a return 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.

31 comments:

  1. Partial code
    retValue, 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
    }

    ReplyDelete
  2. Thank you Ivo, I've updated the check with "if err == nil" to give the same result as you pointed out.

    ReplyDelete
    Replies
    1. Hi Sathish dont you think it is redundant to use this :
      if err == nil {
      }else{
      }

      Instead all you need is
      if err {//Error code
      }else{// Else normal code
      }

      Delete
  3. Hi,
    First, 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

    ReplyDelete
    Replies
    1. Thank you Peter. I checked it based on your feedback and have updated it.

      Delete
  4. Out of curiosity, can you do this: `foo (bar ())` where

    foo := func (a int, b error)
    and
    bar := func () (a int, b error)

    ?

    ReplyDelete
    Replies
    1. Yes, actually. I'm still deciding whether or not that's a terrible, terrible thing though.

      Delete
    2. This is really cool! Nesting functions in functions, you can even go another step futher...

      What 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

      Delete
  5. sorry, but when exactly did the time for improving Golang pass?

    Perhaps "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

    ReplyDelete
  6. Greens Technology's the leading software Training & placement centre Chennai & ( Adyar)
    Manual Testing training in chennai

    ReplyDelete
  7. Thanks for sharing this information and keep updating us regularly. This information is really useful to me.
    PHP Training in Chennai | PHP Course in Chennai | PHP Training institute in Chennai

    ReplyDelete
  8. Thanks for sharing this information and keep updating us regularly. This content is really helped me to know about the Web Designing.
    Web Designing Course in Chennai |Web Designing Training in Chennai | Web Design Course in Chennai

    ReplyDelete


  9. Thanks for posting useful information.You have provided an nice article, Thank you very much for this one. And i hope this will be useful for many people.. and i am waiting for your next post keep on updating these kinds of knowledgeable things...Really it was an awesome article...very interesting to read..
    please sharing like this information......
    Android training in chennai
    Ios training in chennai

    ReplyDelete
  10. It's interesting that many of the bloggers your tips helped to clarify a few things for me as well as giving.. very specific nice content. And tell people specific ways to live their lives.Sometimes you just have to yell at people and give them a good shake to get your point across.
    Web Design Company
    Web Development Company
    Mobile App Development Company

    ReplyDelete

  11. This is excellent information. It is amazing and wonderful to visit your site.Thanks for sharng this information,this is useful to me...
    Android training in chennai
    Ios training in chennai

    ReplyDelete
  12. Thanks for posting useful information.You have provided an nice article, Thank you very much for this one. And i hope this will be useful for many people.. and i am waiting for your next post keep on updating these kinds of knowledgeable things...Really it was an awesome article...very interesting to read..please sharing like this information......
    Web Design Development Company
    Mobile App Development Company

    ReplyDelete

  13. Really it was an awesome article...very interesting to read..You have provided an nice article....Thanks for sharing..
    Web Design Company
    Web Development Company

    ReplyDelete
  14. You have provided an nice article, Thank you very much for this one. And i hope this will be useful for many people.. and i am waiting for your next post keep on updating these kinds of knowledgeable things...

    Android App Development Company

    ReplyDelete
  15. I just want to say that all the information you have given here is awesome...great and nice blog thanks sharing..Thank you very much for this one. And i hope this will be useful for many people.. and i am waiting for your next post keep on updating these kinds of knowledgeable things...
    Web Design Development Company
    Web design Company in Chennai
    Web development Company in Chennai

    ReplyDelete
  16. it is really amazing...thanks for sharing....provide more useful information...
    Mobile app development company

    ReplyDelete
  17. This article is very much helpful and i hope this will be an useful information for the needed one. Keep on updating these kinds of informative things...
    Fitness SMS
    Salon SMS
    Investor Relation SMS

    ReplyDelete
  18. great and nice blog thanks sharing..I just want to say that all the information you have given here is awesome...
    Freshers Jobs in Chennai

    ReplyDelete
  19. I wondered upon your blog and wanted to say that I have really enjoyed reading your blog posts. Any way I’ll be subscribing to your feed and I hope you post again soon.
    iOS App Development Company

    ReplyDelete
  20. Nice to read this article..... Thanks for sharing ....
    Android Training

    ReplyDelete
  21. I wondered upon your blog and wanted to say that I have really enjoyed reading your blog posts. Any way I’ll be subscribing to your feed and I hope you post again soon.

    Texting API
    Text message marketing
    Digital Mobile Marketing
    Sms API
    Sms marketing

    ReplyDelete
  22. Nice it seems to be good post... It will get readers engagement on the article since readers engagement plays an vital role
    snapho

    ReplyDelete

If you think others also will find these tutorials useful, kindly "+1" it above and mention the link in your own blogs, responses, and entries on the net so that others also may reach here. Thank you.