如何在 Go 中转换为类型别名? [英] How to cast to a type alias in Go?

查看:42
本文介绍了如何在 Go 中转换为类型别名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

参见这个游乐场片段.

See 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.")
}

第一个强制转换有效,通过显式声明类型.但第二个演员恐慌.为什么?有没有一种干净的方法可以转换为更长的 func 签名?

The first cast works, by explicitly declaring the type. But the second cast panics. Why? Is there a clean way to cast to a longer func signature?

推荐答案

tl;dr

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

tl;dr

For type assertions (which you use) only the actual type matters. So somethingFuncy is only equal to somethingFuncy and not to func(int) bool.

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

To start with, this has nothing to do with casting. There is no casting in go. There are type assertions and type conversions.

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

You're dealing with a type assertion and are assuming that the same conditions hold as for type conversions. I made the same mistake while reading your question but actually there is a huge difference in behaviour.

假设您有两种类型,例如 inttype MyInt int.这些都是可转换的,因为它们都共享相同的基础类型(转换规则之一),所以这有效(play):

Suppose you have two types, say int and type MyInt int. These are convertible as they both share the same underlying type (one of the conversion rules), so this works (play):

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

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

Now, suppose a is not of type int but of type interface{} (play):

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

编译器会告诉你:

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

cannot convert a (type interface {}) to type MyInt: need type assertion

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

So now we're not doing conversions anymore but assertions. We need to do this (play):

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

现在我们遇到了与您的问题相同的问题.此断言因恐慌而失败:

Now we have the same problem as in your question. This assertion fails with this panic:

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

panic: interface conversion: interface is int, not main.MyInt

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

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

For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion. More precisely, if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T.

所以int 必须与MyInt 相同.type identity 的规则指出(除其他规则外):

So int must be identical to MyInt. The rules of type identity state that (amongst other rules):

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

Two named types are identical if their type names originate in the same TypeSpec.

因为 intMyInt 有不同的声明(TypeSpecs) 它们不相等并且断言失败.当您将 a 断言为 int 时,断言有效.所以你在做什么是不可能的.

As int and MyInt have different declarations (TypeSpecs) they're not equal and the assertion fails. When you assert a to int, the assertion works. So what you're doing is not possible.

实际检查发生 在这段代码中,它只是检查两种类型是否都是和预期的一样.

The actual check happens in this code, which simply checks if both types are the same, as expected.

这篇关于如何在 Go 中转换为类型别名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆