来自 Go 语言中文网微信群群友 Kade 的一道题:
package main
import (
"fmt"
)
type T interface{}
type X string
type Y = string
func main() {
var t T = "abc"
var x X = "abc"
var y Y = "abc"
fmt.Println(t == x)
fmt.Println(t == string(x))
fmt.Println(t == y)
fmt.Println(t == string(y))
}
// 输出什么?
该链接可以直接运行:https://play.studygolang.com/p/Eo47v8jgFKr。
学过 JAVA 的人是不是经常遇到类似 String 的题?通过类似这样的小题,我觉得可以更好地加深对一些知识点的理解、记忆。
您都答对了吗?(答案见文章最后)
简单梳理下涉及到的知识点:
1、type X string 和 type Y = string 的区别
X 是自定义类型,底层类型是 string,X 和 string 是不同的类型;而 Y 只是 string 类型的别名,和 string 是一样的;
2、t、x 和 y 虽然都赋值为字符串 abc,但含义不一样
它们都能赋值为字符串的原因:
1)T 是空接口,可以存放任意类型值;
2)X 的底层类型是 string,因此字符串字面量 abc 可以直接赋值给 x,但下面的情况是不允许的:
var s string = "abc"
var x X = s
这种情况必须进行强制类型转换:
var x X = X(s)
3)Y 是 string 的别名,自然可以直接赋值;
3、接口类型值和非接口类型值比较
该题核心就是考察这个知识点。Go 语言规范里有这样的说明:
A value x of non-interface type X and a value t of interface type T are comparable when values of type X are comparable and X implements T. They are equal if t's dynamic type is identical to X and t's dynamic value is equal to x.
简单翻译下:
当非接口类型 X 的值是可比较的且 X 实现了接口类型 T ,那么 X 的值 x 和 T 的值t 是可比较的。如果 t的动态类型和 X 一致并且 t 的动态值等于 x 的话,那么它们相等。
回到我们的题目:t 是接口类型 T 的值,它的动态类型是 string,动态值是 abc;而 x 的类型是 X,底层类型是 string,所以 t == x 返回 false,t == string(x) 返回 true。至于 Y,因为是 string 的别名,所以 t == y 和 t == string(y) 都返回 true。
所以最后答案是:
false
true
true
true
最后提醒下大家,Go 规范还是应该多翻翻,如果 E 文不好,这里提供了一份中文翻译版,译者 Bekcpear,质量挺高的,可以中英文对照着看。https://hao.studygolang.com/golang_spec.html。