Go 中对多个返回值进行转换/类型断言的惯用方法

在 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)
102472 次浏览

You can't do it in a single line. Your temporary variable approach is the way to go.

By the way, is it called casting when it comes to interfaces?

It is actually called a type assertion. A type cast conversion is different:

var a int
var b int64


a = 5
b = int64(a)

template.Must is the standard library's approach for returning only the first return value in one statement. Could be done similarly for your case:

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


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

By using must you basically say that there should never be an error, and if there is, then the program can't (or at least shouldn't) keep operating, and will panic instead.

func silly() (interface{}, error) {
return "silly", nil
}


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


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

but more likely what you actually want is to use a type switch, like-a-this:

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 is really more about correctness than it is about terseness.

Or just in a single if:

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

Go will take care of the cast inside the if clause and let you access the properties of the casted type.