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 是一种静态类型语言。变量的类型是在编译时确定的。
如果您想动态确定interface
的type
,您可以使用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:将接口动态转换为类型化变量的主要内容,如果未能解决你的问题,请参考以下文章