Golang:将接口动态转换为类型化变量

Posted

技术标签:

【中文标题】Golang:将接口动态转换为类型化变量【英文标题】:Golang: cast an interface to a typed variable dynamically 【发布时间】:2015-01-15 19:55:35 【问题描述】:

在go中,是否可以以某种方式动态转换变量?

例如,如果一个简单的演员是:

var intAge  = interfaceAge.(int)

如果我事先不知道年龄是一个整数怎么办?一个简单的写法是

var x = getType()
var someTypeAge = interfaceAge(.x)

有没有办法实现这样的目标? reflect 包提供了一些在运行时确定或强制转换类型的方法 - 但我找不到像上面提到的任何东西(适用于所有类型的通用方案)。

【问题讨论】:

go 中没有“铸造”。见type switch 你什么时候不知道x有什么类型? Go 是一种具有静态类型的语言。变量的类型在编译时总是已知的。不过,变量的类型可能是接口类型。 您正在寻找一个类型开关,它可以让您根据(静态)类型列表确定您的行为。几乎可以肯定有一种方法可以做任何你想做的事情,你能详细说明你正在尝试什么吗? See the spec/documentation。当且仅当foo 是一个接口类型时,您可以执行x := foo.(int)(或更一般的foo.(T)。它是一个type assertion,如果接口没有,它会在运行时恐慌't hold the ask for type. 你可以使用x, ok := foo.(int),其中 x 将是零值,如果类型断言失败,ok 将是 false。 OP 没有提到type assertions 的名称,但清楚地知道该功能(这就是最初的示例所显示的)。这里的问题是关于任意类型的 dynamic 选择。实际上,通过直接分配可以实现等效效果(但没有任何收获):someTypeAge := interfaceAge。您可以随意传递interface 类型的数据——某些函数(例如fmt.Println(interfaceAge))将动态处理数据。 【参考方案1】:

不,你不能。 Go 是一种静态类型语言。变量的类型是在编译时确定的。

如果您想动态确定interfacetype,您可以使用type switching:

var t interface
t = functionOfSomeType()
switch t := t.(type) 
default:
    fmt.Printf("unexpected type %T", t)       // %T prints whatever type t has
case bool:
    fmt.Printf("boolean %t\n", t)             // t has type bool
case int:
    fmt.Printf("integer %d\n", t)             // t has type int
case *bool:
    fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool
case *int:
    fmt.Printf("pointer to integer %d\n", *t) // t has type *int

【讨论】:

谢谢。我不明白为什么 Go 是静态类型的这一事实意味着您无法在运行时转换类型。例如,在 C# 中,您可以这样做,而 C# 也是一种静态类型语言。你能详细说明一下吗? @orcaman:我认为您可能将接口与泛型混淆了。值的类型在运行时总是是已知的,因为它在编译时是已知的。 Conversions 在 Go 中也有很好的定义。 @orcaman 在 C# 中,您的类型将使用 var 推断出来 .. 就像在 Go 中一样。如果要显式定义类型,则还必须显式将其强制转换为所需的类型(除非您将其装箱)。因此,我不确定我是否将您与 C# 进行比较-情况相同。现在,如果你在谈论 dynamic - 那是完全不同的野兽,当然不能保证编译时类型安全。 @SimonWhitehead 谢谢。在 c# 示例中,我的意思是您可以执行以下操作: var type = obj.GetType();将 Activator.CreateInstance(type) 作为 T 返回;在事先不知道类型的情况下创建任何类型的实例。在 go 中,我可以动态获取类型,但我似乎无法创建该类型的变量(无需自己编写一个涵盖所有类型的丑陋 switch 语句)。 为什么没有提到type assertions?这似乎(几乎?)正是 OP 想要的。

以上是关于Golang:将接口动态转换为类型化变量的主要内容,如果未能解决你的问题,请参考以下文章

Golang type assertion 类型断言

Golang type assertion 类型断言

Golang type assertion 类型断言

将任意 Golang 接口转换为字节数组

(四十五)golang--反射

Golang 入门 : 切片(slice)