为什么map和type断言可以返回1或2值

Gim*_*imo 7 go type-assertion

我们可以做这样的地图:

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)
Run Code Online (Sandbox Code Playgroud)

但我找不到一种方法来定义一个可以返回1值或2值的函数.例如:

func hello() (string, error) {
    return "world", nil
}
Run Code Online (Sandbox Code Playgroud)

调用func时:

v, ok := hello() // valid
v := hello() // invalid
Run Code Online (Sandbox Code Playgroud)

PS:我知道类似template.Must但似乎有所不同,我真的想知道Map和类型断言如何能够做到这一点.

提前致谢.(我清楚了吗?可怜的英语对不起.

pet*_*rSO 6

Go编程语言规范

功能类型

函数类型表示具有相同参数和结果类型的所有函数的集合.

FunctionType   = "func" Signature .
Signature      = Parameters [ Result ] .
Result         = Parameters | Type .
Parameters     = "(" [ ParameterList [ "," ] ] ")" .
ParameterList  = ParameterDecl { "," ParameterDecl } .
ParameterDecl  = [ IdentifierList ] [ "..." ] Type .
Run Code Online (Sandbox Code Playgroud)

空白标识符

空白标识符由下划线字符_表示.

分配

空白标识符提供了一种忽略赋值中右侧值的方法:

x, _ = f()  // evaluate f() but ignore second result value
Run Code Online (Sandbox Code Playgroud)

映射,类型断言和for带有range子句的语句是Go编程语言的特殊功能.对于普通函数类型,不能有可变数量的返回值.

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

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)
}
Run Code Online (Sandbox Code Playgroud)

  • "映射,类型断言和带有范围子句的for语句是Go编程语言的特殊功能." 它在规格中吗? (2认同)

Elw*_*nar 5

映射和类型声明可以执行此操作,因为它们不是函数,而是语言的结构。该行为在规范中进行了描述

映射[K] V类型的映射a上的索引表达式,用于特殊形式的分配或初始化

v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
Run Code Online (Sandbox Code Playgroud)

产生另一个无类型的布尔值。如果键x存在于映射中,则ok的值为true,否则为false。

在特殊形式的赋值或初始化中使用的类型断言

v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
Run Code Online (Sandbox Code Playgroud)

产生另一个无类型的布尔值。如果断言成立,则ok的值为true。否则为false,并且v的值为T类型的零值。在这种情况下,不会发生运行时恐慌。

这不是可以对常规功能执行的操作,因此该Must模式可以明确地再现相同的行为。