如何理解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:
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.
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.
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.