为什么映射和类型断言可以 return 1 或 2 个值?

Why map and type assertion can return 1 or 2 values?

要定义一个地图,我们可以做这样的事情:

value, present := m["key"]

或:

value := m["key"]

使用类型断言,我们可以:

var i interface{} = "hello"

s := i.(string)
fmt.Println(s)

s, ok := i.(string)
fmt.Println(s, ok)

但我找不到定义可以 return 1 个值或 2 个值的函数的方法。

例如:

func hello() (string, error) {
    return "world", nil
}

当我调用这个函数时,我得到:

v, ok := hello() // valid
v := hello() // invalid

PS:我知道 template.Must 之类的东西是如何工作的,但它似乎有所不同。我真的很想知道 Map 和类型断言是如何发挥魔力的,所以我可以将它应用到函数中。

提前致谢。 (我清楚了吗?我的英语不好抱歉)。

映射和类型断言可以做到这一点,因为它们不是函数,而是语言的结构。规范中描述了该行为

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.

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.

这不是可以在一般函数上完成的事情,因此 Must 模式明确地重现了相同的行为。

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

映射、类型断言和带有 range 子句的 for 语句是 Go 编程语言的特殊功能。普通函数类型不能有可变数量的 return 个值。

您可以忽略带有下划线 (_)、空白标识符的 return 值,或者您可以使用包装函数。例如,

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)
}