Why map and type assertion can return 1 or 2 values?
Map and type assertions can do this because they are not functions, but structures of the language. The behavior is described in the spec
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]
yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.
and
A type assertion used in an assignment or initialization of the special form
v, ok = x.(T) v, ok := x.(T) var v, ok = x.(T)
yields an additional untyped boolean value. The value of ok is true if the assertion holds. Otherwise it is false and the value of v is the zero value for type T. No run-time panic occurs in this case.
It is not something that can be done on general functions, hence the Must
pattern that explicitely reproduce the same behavior.
The Go Programming Language Specification
Function types
A function type denotes the set of all functions with the same parameter and result types.
FunctionType = "func" Signature . Signature = Parameters [ Result ] . Result = Parameters | Type . Parameters = "(" [ ParameterList [ "," ] ] ")" . ParameterList = ParameterDecl { "," ParameterDecl } . ParameterDecl = [ IdentifierList ] [ "..." ] Type .
Blank identifier
The blank identifier is represented by the underscore character _.
Assignments
The blank identifier provides a way to ignore right-hand side values in an assignment:
x, _ = f() // evaluate f() but ignore second result value
Maps, type assertions, and the for
statement with a range
clause are special features of the Go programming language. You can't have a variable number of return values for an ordinary function type.
You can ignore a return value with an underscore (_), the blank identifier, or you can use a wrapper function. For example,
package main
import "fmt"
func two() (int, bool) {
return 42, true
}
func one() int {
r, _ := two()
return r
}
func main() {
r, ok := two()
r, _ = two()
r = one()
fmt.Println(r, ok)
}