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

Mat*_*att 35 types casting go

看到这个游乐场片段.

相关代码:

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.")
}
Run Code Online (Sandbox Code Playgroud)

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

nem*_*emo 58

TL;博士

对于类型断言(您使用),只有实际类型很重要.所以somethingFuncy只等于somethingFuncy而不是func(int) bool.

说明

首先,这与铸造无关.去没有铸造.有类型断言类型转换.

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

假设你有两种类型,比如说inttype MyInt int.这些是可转换的,因为它们共享相同的底层类型(转换规则之一),所以这适用(播放):

var a int = 10
var b MyInt = MyInt(a)
Run Code Online (Sandbox Code Playgroud)

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

var a interface{} = int(10)
var b MyInt = MyInt(a)
Run Code Online (Sandbox Code Playgroud)

编译器会告诉你:

无法将(类型接口{})转换为MyInt类型:需要类型断言

所以现在我们不再做转换了,而是断言.我们需要这样做():

var a interface{} = int(10)
var b MyInt = a.(MyInt)
Run Code Online (Sandbox Code Playgroud)

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

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

原因在规范的类型断言部分中说明:

对于接口类型和类型的表达式x T,主表达式x.(T) 断言x不是,nil并且存储的值x是类型T.该表示法 x.(T)称为类型断言. 更确切地说,如果T不是接口类型,x.(T)则断言动态类型x与类型相同T.

所以int必须相同MyInt.类型标识的规则规定(以及其他规则):

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

由于int并且MyInt具有不同的声明(TypeSpecs),它们不相等并且断言失败.断言aint,断言有效.所以你正在做的事情是不可能的.

奖金:

实际检查发生在此代码中,它只是检查两种类型是否与预期相同.

  • [TypeSpec 定义](http://golang.org/ref/spec#Type_declarations) 中有一些示例。在答案中,我使用了“MyInt”,它具有 TypeSpec“MyInt int”。因此,“MyInt”等于“MyInt”,但不等于“type MySecondInt int”,因为“MySecondInt int”不等于“MyInt int”(名称不同)。 (2认同)

aga*_*eld 16

2017年更新:

使用Go 1.9中的类型断言,您只需添加=定义类型的位置即可.

type somethingFuncy = func(int) bool
Run Code Online (Sandbox Code Playgroud)

这告诉编译器这somethingFuncy是一个替代名称func(int) bool.

  • 请注意,如果执行此操作,您将无法向新类型添加函数,它只是一个别名.你会得到一个恼人的`无法定义非本地类型的新方法`错误.或者至少我在尝试使用基于字符串的自定义类型时做了. (4认同)

Fel*_*xCQ 7

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

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

请注意,由于底层类型顾名思义是动态的,因此测试类型断言是成功还是失败是个好主意.另一方面,类型转换的正确性由编译器强制执行.

这是您的游乐场片段略有修改:http://play.golang.org/p/FZv06Zf7xi