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

Types 如何在Go中强制转换为类型别名?,types,casting,go,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 signat

请参见

相关代码:

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.")
}
第一个强制转换通过显式声明类型来工作。但第二个问题引发了恐慌。为什么?是否有一种干净的方法可以转换为较长的func签名?

tl;博士
对于类型断言(您使用的),只有实际的类型才重要。所以
somethingFuncy
只等于
somethingFuncy
,而不等于
func(int)bool

解释 首先,这与铸造无关。围棋中没有演员。 有和

您正在处理一个类型断言,并假设相同的条件成立 至于类型转换。我在读你的问题时也犯了同样的错误,但事实上行为上有很大的不同

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

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

编译器将告诉您:

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

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

现在我们的问题和你的问题一样。此断言因以下原因而失败:

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

其原因在规范的附录中说明:

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

所以
int
必须与
MyInt
相同。国家规定 (除其他规则外):

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

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

奖金: 实际的检查会发生,它只是检查两种类型是否相同
同样,正如所料。

为了完成nemo令人敬畏的回答,请注意,虽然您不能直接从给定动态类型(例如,
int
)的接口(例如,
interface{}
)跳到另一种类型(例如,
typemyint
),但您可以依次执行两个步骤:

  • 断言变量的动态类型是您期望的类型
  • 将该断言的结果转换为您选择的类型
注意,由于底层类型(顾名思义)是动态的,因此最好测试类型断言是成功还是失败。 另一方面,类型转换的正确性由编译器强制执行


下面是您的游乐场代码片段,稍作修改:

我相信您需要的是类型别名。提案已被接受,应在Go 1.9中。即

TypeSpec=标识符[“=”]类型。

参考文献

2017年更新: 使用Go 1.9中的类型断言,您只需在定义类型的位置添加
=

type somethingFuncy = func(int) bool

这告诉编译器,
somethingFuncy
func(int)bool
的替代名称

如果它们的类型名源自相同的类型规范,我无法理解
。你能给我举个例子吗?谢谢。下面有一些例子。在回答中,我使用了
MyInt
,它的类型是spec
MyInt
。因此,
MyInt
等于
MyInt
,但不等于
type MySecondInt
,因为
MySecondInt
不等于
MyInt
(名称不同)。很好的解释。我正在考虑为从另一个包导入的结构创建别名。我只是在做
类型TreeNode.Node
,但当结构成员,即
节点.Left
被分配一个值/地址时,它给出了
需要类型断言
错误。这个解释让我了解了如何实际使用别名,现在在将
类型TreeNode tree.Node
更改为
类型TreeNode=tree.Node
后,它可以正常工作。感谢您的详细解释。请注意,如果您这样做,您将无法向新类型添加函数,它将只是一个别名。您将得到一个恼人的
无法在非本地类型上定义新方法的错误。或者至少当我尝试使用基于字符串的自定义类型时,我这样做了。旧注释是对旧答案的注释,但为了子孙后代:它现在完全可以工作了,您可以添加方法,这是我正在使用的一种模式,go1.15仍然会出错:
无法在非本地类型上定义新方法
somethingFuncy
不是
funcy(I int)bool
的类型别名。这是一种全新的类型,定义为
funcy(i int)bool
。这就像定义
类型A结构{Foo string}
类型B结构{Foo string}
一样。他们是不同的。
var a interface{} = int(10)
var b MyInt = MyInt(a)
var a interface{} = int(10)
var b MyInt = a.(MyInt)
type somethingFuncy = func(int) bool