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

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

Idiomatic way to do conversion/type assertion on multiple return values in Go

问题

在Go语言中,将多个返回值转换为特定类型的惯用方法是使用临时变量。你需要使用一个临时变量来接收多个返回值,然后将其转换为所需的类型。以下是示例代码:

package main

import "fmt"

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

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

func main() {
	// 对于一个返回值,可以直接这样做
	str1 := oneRet().(string)
	fmt.Println("String 1: " + str1)

	// 对于两个返回值,不太容易
	//str2, err := twoRet().(string) // 不可行
	// 我真的需要使用一个临时变量吗?
	temp, err := twoRet()
	str2 := temp.(string)
	fmt.Println("String 2: " + str2)

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

顺便问一下,当涉及到接口时,这被称为类型断言吗?

i := interface.(int)
英文:

What is the idiomatic way to cast multiple return values in Go?

Can you do it in a single line, or do you need to use temporary variables such as I've done in my example below?

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

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

i := interface.(int)

答案1

得分: 73

你不能在一行中完成它。
你的临时变量方法是正确的。

顺便问一下,当涉及到接口时,它被称为转换吗?

实际上,它被称为type assertion
类型转换是不同的:

var a int
var b int64

a = 5
b = int64(a)
英文:

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 <strike>cast</strike> conversion is different:

var a int
var b int64

a = 5
b = int64(a)

答案2

得分: 44

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

v, err := silly()
if err != nil {
// 处理错误
}

s, ok := v.(string)
if !ok {
// 断言失败
}

但更有可能的是,你实际上想要使用类型切换,像这样:

switch t := v.(type) {
case string:
// t 是一个字符串
case int:
// t 是一个整数
default:
// t 是我们没有命名的其他类型
}

Go 更关注正确性而不是简洁性。

英文:
func silly() (interface{}, error) {
    return &quot;silly&quot;, 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&#39;t name.
}

Go is really more about correctness than it is about terseness.

答案3

得分: 30

如果只是一个if语句:

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

Go语言会在if语句中处理类型转换,并允许您访问转换后类型的属性。

英文:

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.

答案4

得分: 12

template.Must 是标准库中只返回一个语句中的第一个返回值的方法。对于你的情况,可以类似地实现:

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

// 使用方法:
str2 := must(twoRet()).(string)

通过使用 must,你基本上表示不应该出现错误,如果出现错误,程序将无法(或至少不应该)继续运行,而是会引发 panic。

英文:

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.

huangapple
  • 本文由 发表于 2012年7月10日 04:58:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/11403050.html
匿名

发表评论

匿名网友

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

确定