如何理解golang多返回值

如何理解golang多返回值

问题描述:

Golang supports assigning multiple return values to multiple left hand side variables. E.g:

func test() (string, string) {
  return "1", "1"
}

a, b := test()

or

a, _ := test()

and the number of receiving variables and return values must match:

b = test()   //wrong

But for some built-in types, such as [] or <-, a variable number of return values are supported

key, exist := map[key]

key := map[key]

I can read value from channel like this

c <- myChan

c, exist <- myChan

How can we explain the inconsistency? Is this a capability reserved to the core go runtime/language?

This behavior clearly specified in the golang specification:

  1. Receive operator

A receive expression used in an assignment or initialization of the special form

x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch
var x, ok T = <-ch

yields an additional untyped boolean result reporting whether the communication succeeded. The value of ok is true if the value received was delivered by a successful send operation to the channel, or false if it is a zero value generated because the channel is closed and empty.

  1. Index expression

An index expression on a map a of type map[K]V used in an assignment or initialization of the special form

v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]

yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.

  1. Assignments

A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables. There are two forms. In the first, the right hand operand is a single multi-valued expression such as a function call, a channel or map operation, or a type assertion. The number of operands on the left hand side must match the number of values. For instance, if f is a function returning two values,

x, y = f()

assigns the first value to x and the second to y. In the second form, the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth operand on the left.

Therefore as you can see this behavior being specified by language design and you cannot achieve those specified for Receive operator and Index expression by yourself.

You are confusing multiple values returned from a function with the so-called "comma ok" idiom.

With a function's return values you must either handle all of them, or none of them. Simple.

"Comma ok" is more subtle. Often the behavior is changed if you have a second value specified. Consider these statements:

v, ok := x.(int)
// vs
v := x.(int)

If x is an interface holding an integer, all is well, however, if x holds a different type the first statement will work (returning 0, false), and the second one will panic.

Each type of statement with a "comma ok" form is a different special case, and they are not the same as other kinds of multiple assignments (such as multiple function return values). You cannot compare them, each is its own thing, with its own rules.