首页 文章

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

提问于
浏览
28

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 回答

  • 52

    tl;博士

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

    解释

    首先,这与铸造无关 . 去没有铸造 . 有type assertionstype conversions .

    您正在处理类型断言,并假设条件 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类型:需要类型断言

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

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

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

    panic:接口转换:接口是int,而不是main.MyInt

    其原因在规范的type assertions section中说明:

    对于接口类型和类型T的表达式x,主表达式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

    更新2017:

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

    type somethingFuncy = func(int) bool
    

    这告诉编译器 somethingFuncyfunc(int) bool 的备用名称 .

  • 14

    只是为了完成nemo 's awesome answer, note that while you can' t直接从给定动态类型(例如, int )的接口(例如, int )跳转到另一种类型(例如, type MyInt int ),您可以一个接一个地执行这两个步骤:

    • 断言变量的动态类型是您所期望的;

    • 将该断言的结果转换为您选择的类型 .

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

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

  • 6

    我相信类型别名是你想要的 . 提案被接受,应该在Go 1.9中 . IE浏览器 .

    TypeSpec = identifier [ "=" ] Type .

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

相关问题