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

时间:2016-03-27 06:59:41

标签: 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)

但是我无法找到一种方法来定义一个可以返回1值或2值的func。 例如:

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

调用func:

v, ok := hello() // valid
v := hello() // invalid
PS:我知道像template.Must这样的东西,但看起来不一样,我真的想知道Map和类型断言是如何做到的。

提前致谢。 (我清楚了吗?可怜的英语抱歉。

2 个答案:

答案 0 :(得分:5)

  

The Go Programming Language Specification

     

Function types

     

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

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

Blank identifier

     

空白标识符由下划线字符_。

表示      

Assignments

     

空白标识符提供了忽略右侧值的方法   在作业中:

x, _ = f()  // evaluate f() but ignore second result value

映射,类型断言以及带有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)
}

答案 1 :(得分:4)

Map和type断言可以做到这一点,因为它们不是函数,而是语言的结构。该行为在规范

中描述
  

分配中使用的类型map [K] V的映射a上的索引表达式   或初始化特殊表格

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

产生一个额外的无类型布尔值。如果是,则ok的值为true   键x出现在地图中,否则为false。

  

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

v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
     

产生一个额外的无类型布尔值。如果是,则ok的值为true   断言成立。否则它是假的,v的值是   类型T的值为零。在这种情况下不会发生运行时混乱。

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