如何在Go中转换为类型别名?

时间:2013-10-24 21:54:00

标签: types casting go

请参阅 this playground snippet

相关代码:

type somethingFuncy func(int) bool

func funcy(i int) bool {
    return i%2 == 0
}

var a interface{} = funcy

func main() {

    _ = a.(func(int) bool)  // Works

    fmt.Println("Awesome -- apparently, literally specifying the func signature works.")

    _ = a.(somethingFuncy)  // Panics

    fmt.Println("Darn -- doesn't get here. But somethingFuncy is the same signature as func(int) bool.")
}

第一个演员通过明确声明类型来工作。但第二次演员恐慌。为什么?是否有一种干净的方式来转换为更长的功能签名?

4 个答案:

答案 0 :(得分:56)

TL;博士

对于类型断言(您使用的),仅实际类型很重要。因此somethingFuncy仅等于somethingFuncy而不是func(int) bool

解释

首先,这与投射无关。去没有铸造。 有type assertionstype conversions

您正在处理类型断言,并假设条件相同 至于类型转化。我在阅读你的问题时犯了同样的错误,但实际上行为存在巨大差异。

假设您有两种类型,例如inttype MyInt int。这两者都是可转换的 共享相同的基础类型(转换规则之一),因此这有效(play):

var a int = 10
var b MyInt = MyInt(a)

现在,假设a不是int类型,而是类型interface{}play):

var a interface{} = int(10)
var b MyInt = MyInt(a)

编译器会告诉你:

  

无法将(类型接口{})转换为MyInt类型:need type assertion

现在我们不再进行转换断言。我们需要这样做(play):

var a interface{} = int(10)
var b MyInt = a.(MyInt)

现在我们遇到与您的问题相同的问题。这种说法因恐慌而失败:

  

恐慌:界面转换:界面是int,而不是main.MyInt

原因在type assertions section规范中列出:

  

对于接口类型的表达式x和类型T,主表达式x.(T)   断言x不是nil,而x中存储的值属于T类型。符号   x.(T)被称为类型断言。   更确切地说,如果T不是接口类型,x.(T)断言动态   x的类型与T 类型相同。

因此int必须与MyInt相同。 type identity的规则说明了这一点 (以及其他规则):

  

如果两个命名类型的类型名称源自相同的TypeSpec,则它们是相同的。

由于intMyInt有不同的声明(TypeSpecs),所以它们不相等 并且断言失败了。当您将a声明为int时,断言有效。 所以你正在做的事情是不可能的。

加成:

实际检查发生in this code,它只是检查两种类型是否都是 同样的,如预期的那样。

答案 1 :(得分:16)

2017年更新:

使用Go 1.9中的类型断言,只需在定义类型的地方添加=即可。

type somethingFuncy = func(int) bool

这告诉编译器somethingFuncyfunc(int) bool的替代名称。

答案 2 :(得分:7)

只是为了完成nemo的精彩回答,请注意,虽然您不能直接从给定动态类型(例如interface{})的接口(例如,int)跳转到另一种类型(例如,type MyInt int),你可以一个接一个地做两个步骤:

  • 断言您的变量的动态类型是您所期望的;
  • 将该断言的结果转换为您选择的类型。

请注意,由于基础类型,顾名思义, dynamic ,因此最好测试类型断言是成功还是失败。 另一方面,类型转换的正确性由编译器强制执行。

以下是您稍微修改过的游乐场代码段:http://play.golang.org/p/FZv06Zf7xi

答案 3 :(得分:1)

我相信类型别名就是你想要的。提案被接受,应该在Go 1.9中。即

TypeSpec = identifier [ "=" ] Type .

参考
https://github.com/golang/go/issues/18130
https://github.com/golang/proposal/blob/master/design/18130-type-alias.md