package main
import "fmt"
type I int
type M map[string]interface{}
type M2 map[string]interface{}
func main() {
var m M = M{"hello": "world"}
printM(m) //可以
var num I = 123
printI(num) //不行的
printM2(m) //不行的
}
func printI(i int) {
fmt.Println(i)
}
func printM(m map[string]interface{}) {
fmt.Println(m)
}
func printM2(m M2) {
fmt.Println(m)
}
众所周知, I
和 int
是两个类型,但是为啥 M
能直接被当做 map[string]interface{}
?
1
iRiven 2018-07-13 12:49:40 +08:00 via Android
golang 类型不能隐式转换
|
2
ferrum 2018-07-13 13:00:09 +08:00 via iPhone
如果用了 vscode-go 插件,或者其他的 IDE,在写代码时就有提示类型不正确吧。
|
3
zhs227 2018-07-13 13:08:03 +08:00
可以使用类型断言,或者是使用别名。 别名的方式是 type I = int, 支持 1.9 以上版本,但有些其它的限制。
|
4
yufpga 2018-07-13 13:39:41 +08:00
I, M, M2,int, map[string]interface{} 确实是五种不同的类型,所以 printI(num), printM2(m) 不能执行是对的,也能够理解。但是 printM(m)为什么可以,说实话,我回答不上来,逻辑上讲不通。只能归结为 golang 中的 map 是一种引用类型,有我们不知道的其他原因。假如楼主尝试一下 go 中的其他引用类型对比 map, 比如
type C chan int func printC(c chan int){} 也能得到类似 map 的结果, 而我尝试了其他的值类型(包括定义一个 struct), 得到的结果是与 int 这种结果一致的。额外说一下,golang 中只有 map, slice, channel 三种引用累心,其余都是值类型。 |
7
hheedat OP @yufpga 有答案了
https://golang.org/ref/spec#Assignability x's type V and T have identical underlying types and at least one of V or T is not a defined type. all numeric types are defined types |
8
yufpga 2018-07-13 18:21:59 +08:00
@hheedat 谢谢, 明白了. 总结一下: 根据文档描述 The new type is called a defined type. It is different from any other type, including the type it is created from. 那么所有通过 type 定义的结构体 /类型也都是 defined type(当然不全包括 type T1 = T 这种形式定义的部分新类型). 文档上还说 Boolean type, numberic type, string type 都是 defined type.
那么问题来了,有哪些不是 defined type: map, channel, slice, pointer, 函数类型 ...(欢迎继续补充, 其实这些类型看上去还是挺有规律的) |