A. Solomatin
A. Solomatin

Reputation: 21

What's the difference between these two variants?

I tried to make my own code for learning how to return multiple values in main function:

package main

import "fmt"

func main() {
    fmt.Println("Enter a integer:")
    var I int
    fmt.Scanf("%d", &I)
    fmt.Println("Accepted:", I)

    O := half(I)
    fmt.Println("Returned:", O)
}

func half(N int) (int, bool) {
    var NA int
    NA = N / 2
    if NA%2 == 0 {
        fmt.Println("even")
        return NA, true
    } else {
        fmt.Println("odd")
        return NA, false
    }
}

And given error: half.go|11| multiple-value half() in single-value context. However another variant are working:

package main

import (
    "fmt"
)

func half(number int) (int, bool) {
    if x := int(number % 2); x == 0 {
        return x, true
    } else {
        return x, false
    }
}

func main() {
    fmt.Println(half(1))
    fmt.Println(half(2))
}

What am I doing wrong? How to overcome my error?

Upvotes: 2

Views: 91

Answers (2)

icza
icza

Reputation: 417672

If a function has 2 return values, you have to "expect" both of them or none at all. More on this: Return map like 'ok' in Golang on normal functions

Your half() function has 2 return values, so when using a short variable declaration to store the returned values in variables, you have to provide 2 variables:

O, even := half(I)
fmt.Println("Returned:", O, even)

In the second case, you're not storing the returned values, you are passing them to fmt.Println() which has the signature:

func Println(a ...interface{}) (n int, err error)

fmt.Println() has a variadic parameter, so you can pass any number of arguments to it. What happens here is that all the multiple return values of half() are passed as the value of the variadic parameter of Println(). This is allowed and detailed in Spec: Calls:

As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value. If f has a final ... parameter, it is assigned the return values of g that remain after assignment of regular parameters.

Note that when doing so, you are not allowed to pass / provide extra parameters, so for example the following is also a compile-time error:

fmt.Println("Returned:", half(10))
// Error: multiple-value half() in single-value context

Check out these similar questions:

Go: multiple value in single-value context

Avoid nesting from conjunction with function that returns 2 values in go?

Upvotes: 3

captncraig
captncraig

Reputation: 23088

fmt.Println accepts any number of arguments, so is ok accepting the results of half.

In the first one, you need to provide places for both variables. Either:

i,b := half(2)

or

i, _ := half(2)

if you don't need the second return.

Upvotes: 1

Related Questions