2

在 Go 教程中经常看到以下代码:

a := foo()
b, c := foo()

或者实际上我看到的是:

m["Answer"] = 48
a := m["Answer"]
v, ok := m["Answer"]

定义了多少个 foo()?

是两种,一种具有一种返回类型,另一种具有两种返回类型?

或者只是一个定义了两个返回类型的 foo(),并且当只需要一个返回值 () 时,又以某种方式神奇地a := foo()省略了另一个返回值?

我试过

package main

func main() {
    a := foo()
    a = 1
}

func foo() (x, y int) {
    x = 1
    y = 2
    return
}

func foo() (y int) {
    y = 2
    return
}

但我收到错误消息foo redeclared in this block

4

2 回答 2

7

虽然一些内置操作同时支持单返回值模式和多返回值模式(例如从映射读取、类型断言或在循环中使用 range 关键字),但此功能不适用于用户定义的函数。

如果您想要具有不同返回值的函数的两个版本,则需要为它们指定不同的名称。

于 2013-10-31T05:38:08.907 回答
3

Effective Go教程对此有一些很好的信息。

基本上,一个函数定义了它的语句返回多少个值return,以及它的函数签名。

要忽略一个或多个返回值,您应该使用空白标识符_(下划线)。

例如:

package main

import "fmt"

func singleReturn() string {
    return "String returned"
}

func multiReturn() (string, int) {
    return "String and integer returned", 1
}

func main() {
    s := singleReturn()
    fmt.Println(s)
    s, i := multiReturn()
    fmt.Println(s, i)
}

操场

您给出的v, ok := m["answer"]示例是“逗号,ok”习语的示例(也在上面的 Effective Go 链接中描述)。链接的文档使用类型断言作为它的使用示例:

要提取我们知道值中的字符串,我们可以这样写:

str := value.(string)

但如果事实证明该值不包含字符串,则程序将因运行时错误而崩溃。为了防止这种情况发生,请使用“comma, ok”习惯用法来安全地测试该值是否为字符串:

str, ok := value.(string)
if ok {
    fmt.Printf("string value is: %q\n", str)
} else {
    fmt.Printf("value is not a string\n")
}

如果类型断言失败,str 将仍然存在并且是 string 类型,但它将具有零值,即一个空字符串。

于 2013-10-31T05:26:51.257 回答