如何使函数支持一个或两个返回值?

huangapple go评论72阅读模式
英文:

how to make function support one or two return value

问题

在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在此块中重新声明

英文:

in go tutorial following code is often seen:

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

or actually what I see is:

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

how many foo() is defined?

Is it two, one with one return type, another with two return type?

Or just one foo() with two return type defined, and somehow magically when only need one return value (a := foo()), another return value is omitted?

I tried

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
}

But I got error message foo redeclared in this block

答案1

得分: 7

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

如果你想要两个具有不同返回值的函数版本,你需要给它们不同的名称。

英文:

While some built in operations support both single and multiple return value modes (like reading from a map, type assertions, or using the range keyword in loops), this feature is not available to user defined functions.

If you want two versions of a function with different return values, you will need to give them different names.

答案2

得分: 3

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

基本上,一个函数通过其return语句和函数签名来定义它返回多少个值。

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

例如:

package main

import "fmt"

func singleReturn() string {
    return "返回的字符串"
}

func multiReturn() (string, int) {
    return "返回的字符串和整数", 1
}

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

Playground

你提供的v, ok := m["answer"]示例是“逗号,ok”习惯用法的一个例子(也在上面的《Effective Go》链接中有描述)。链接的文档使用类型断言作为它的用例:

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

str := value.(string)

但是,如果结果发现值不包含字符串,程序将崩溃并出现运行时错误。为了防止这种情况发生,使用“逗号,ok”习惯用法来安全地测试值是否为字符串:

str, ok := value.(string)
if ok {
    fmt.Printf("字符串值为:%q\n", str)
} else {
    fmt.Printf("值不是字符串\n")
}

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

英文:

The Effective Go tutorial has some good information on this.

Basically, a function defines how many values it returns with it's return statement, and it's function signature.

To ignore one or more of the returned values you should use the Blank Identifier, _(Underscore).

For example:

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

Playground

The v, ok := m["answer"] example you've given is an example of the "comma, ok" idiom (Also described in the Effective Go link above). The linked documentation uses type assertions as an example of it's use:

>>To extract the string we know is in the value, we could write:

str := value.(string)

>>But if it turns out that the value does not contain a string, the program will crash with a run-time error. To guard against that, use the "comma, ok" idiom to test, safely, whether the value is a string:

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

>>If the type assertion fails, str will still exist and be of type string, but it will have the zero value, an empty string.

huangapple
  • 本文由 发表于 2013年10月31日 13:11:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/19698885.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定