英文:
Why map and type assertion can return 1 or 2 values?
问题
定义一个映射(map)时,我们可以这样做:
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)
但是我找不到一种定义一个函数可以返回一个值或两个值的方法。
例如:
func hello() (string, error) {
return "world", nil
}
当我调用这个函数时,我得到:
v, ok := hello() // 有效
v := hello() // 无效
PS:我知道类似template.Must
的用法,但它似乎不同。我真的想知道映射和类型断言是如何实现的,这样我就可以将其应用到函数中。
提前感谢你的帮助。(我表达清楚了吗?我英文不好,抱歉)。
英文:
To define a map, we can do such a thing:
value, present := m["key"]
or:
value := m["key"]
and with type assertion, we can do:
var i interface{} = "hello"
s := i.(string)
fmt.Println(s)
s, ok := i.(string)
fmt.Println(s, ok)
but I can't find a way to define a func that can return 1 value or 2-values.
For instance:
func hello() (string, error) {
return "world", nil
}
When I invoke this func I get:
v, ok := hello() // valid
v := hello() // invalid
PS: I know how something like template.Must
works, but it seems different. I really want to know how Map and type assertion can do the magic, so I can apply it to functions.
Thanks in advance. (Am I clear? I have poor English sorry).
答案1
得分: 7
《Go编程语言规范》
函数类型
函数类型表示具有相同参数和结果类型的所有函数的集合。
FunctionType = "func" Signature .
Signature = Parameters [ Result ] .
Result = Parameters | Type .
Parameters = "(" [ ParameterList [ "," ] ] ")" .
ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
空白标识符
空白标识符用下划线字符 _ 表示。
赋值
空白标识符提供了一种忽略赋值语句中右侧值的方式:
x, _ = f() // 调用 f(),但忽略第二个结果值
映射、类型断言和带有 range 子句的 for 语句是 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)
}
英文:
> 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)
}
答案2
得分: 6
地图和类型断言可以做到这一点,因为它们不是函数,而是语言的结构。该行为在规范中有描述:
对于类型为 map[K]V 的地图 a,在赋值或初始化的特殊形式中使用的索引表达式
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
会产生一个额外的无类型布尔值。如果键 x 存在于地图中,则 ok 的值为 true,否则为 false。
而对于在赋值或初始化的特殊形式中使用的类型断言
v, ok = x.(T)
v, ok := x.(T)
var v, ok = x.(T)
也会产生一个额外的无类型布尔值。如果断言成立,则 ok 的值为 true。否则,ok 的值为 false,v 的值为类型 T 的零值。在这种情况下不会发生运行时恐慌。
这不是通用函数可以做到的事情,因此需要使用 Must
模式来显式地重现相同的行为。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论