2 回答
TA贡献1864条经验 获得超2个赞
我相信这里最初作者的逻辑是命名类型的命名是有原因的 - 它代表不同的东西,而不仅仅是底层类型。
我想我在 golang-nuts 的某个地方读过它,但不记得确切的讨论。
考虑以下示例:
type Email string
您将其命名为 Email,因为您需要表示电子邮件实体,而 'string' 只是它的简化表示,足够一开始。但稍后,您可能希望将 Email 更改为更复杂的内容,例如:
type Email struct {
Address string
Name string
Surname string
}
假设它是一个字符串,这将破坏所有与 Email 一起使用的代码。
TA贡献1829条经验 获得超9个赞
这是因为 Go 没有类继承。它使用结构组合代替。命名类型不会从它们的底层类型继承属性(这就是为什么它不被称为“基本类型”)。
因此,当您specialString使用预定义类型的基础类型声明命名类型时string,您的新类型与基础类型完全不同。这是因为 Go 假设您希望为新类型分配不同的行为,并且在运行时之前不会检查其基础类型。这就是 Go 既是静态语言又是动态语言的原因。
当你打印
fmt.Println(reflect.TypeOf(ss)) // specialString
你得到specialString,不是string。如果你看一下Println()定义如下:
func Println(a ...interface{}) (n int, err error) {
return Fprintln(os.Stdout, a...)
}
这意味着您可以打印任何预先声明的类型(int、float64、string),因为它们都实现了至少零个方法,这使得它们已经符合空接口并作为“可打印”传递,但不是您的命名类型specialString,它仍然未知在编译期间去。我们可以通过打印 our interface{}against的类型来检查specialString。
type specialString string
type anything interface{}
s := string("cheese")
ss := specialString("special cheese")
at := anything("any cheese")
fmt.Println(reflect.TypeOf(ss)) // specialString
fmt.Println(reflect.TypeOf(s)) // string
fmt.Println(reflect.TypeOf(at)) // Wow, this is also string!
你可以看到它specialString一直在调皮它的身份。现在,看看它在运行时传递给函数时的效果
func printAnything(i interface{}) {
fmt.Println(i)
}
fmt.Println(ss.(interface{})) // Compile error! ss isn't interface{} but
printAnything(ss) // prints "special cheese" alright
ss就interface{}功能而言已经过得去。到那时,Go 已经创建了ss一个interface{}.
- 2 回答
- 0 关注
- 191 浏览
添加回答
举报