83

在 Go 中转换多个返回值的惯用方式是什么?

您可以在一行中完成,还是需要使用临时变量,例如我在下面的示例中所做的?

package main

import "fmt"

func oneRet() interface{} {
    return "Hello"
}

func twoRet() (interface{}, error) {
    return "Hejsan", nil
}

func main() {
    // With one return value, you can simply do this
    str1 := oneRet().(string)
    fmt.Println("String 1: " + str1)

    // It is not as easy with two return values
    //str2, err := twoRet().(string) // Not possible
    // Do I really have to use a temp variable instead?
    temp, err := twoRet()
    str2 := temp.(string)
    fmt.Println("String 2: " + str2 )


    if err != nil {
        panic("unreachable")
    }   
}

顺便问一下,casting当涉及到接口时,它会被调用吗?

i := interface.(int)
4

4 回答 4

72

你不能在一行中做到这一点。您的临时变量方法是可行的方法。

顺便说一句,当涉及到接口时,它是否称为强制转换?

它实际上被称为类型断言。类型转换是不同的:

var a int
var b int64

a = 5
b = int64(a)
于 2012-07-09T21:26:53.207 回答
39
func silly() (interface{}, error) {
    return "silly", nil
}

v, err := silly()
if err != nil {
    // handle error
}

s, ok := v.(string)
if !ok {
    // the assertion failed.
}

但更可能的是您真正想要的是使用类型开关,例如:

switch t := v.(type) {
case string:
    // t is a string
case int :
    // t is an int
default:
    // t is some other type that we didn't name.
}

Go 实际上更多的是关于正确性,而不是关于简洁性。

于 2012-07-20T13:40:16.773 回答
18

或者只是一个如果:

if v, ok := value.(migrater); ok {
    v.migrate()
}

Go 将处理 if 子句中的转换,并让您访问转换类型的属性。

于 2017-03-09T10:53:39.980 回答
12

template.Must是标准库在一个语句中只返回第一个返回值的方法。可以为您的情况类似地完成:

func must(v interface{}, err error) interface{} {
    if err != nil {
        panic(err)
    }
    return v
}

// Usage:
str2 := must(twoRet()).(string)

通过使用must你基本上说不应该有错误,如果有,那么程序不能(或至少不应该)继续运行,而是会恐慌。

于 2012-07-09T21:39:52.087 回答