V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
hheedat
V2EX  ›  Go 编程语言

问一个 GO 的底层类型问题

  •  
  •   hheedat · 2018-07-13 12:41:10 +08:00 · 2198 次点击
    这是一个创建于 2355 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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)
    }
    
    

    众所周知, Iint 是两个类型,但是为啥 M 能直接被当做 map[string]interface{} ?

    proxy

    8 条回复    2018-07-13 18:21:59 +08:00
    iRiven
        1
    iRiven  
       2018-07-13 12:49:40 +08:00 via Android
    golang 类型不能隐式转换
    ferrum
        2
    ferrum  
       2018-07-13 13:00:09 +08:00 via iPhone
    如果用了 vscode-go 插件,或者其他的 IDE,在写代码时就有提示类型不正确吧。
    zhs227
        3
    zhs227  
       2018-07-13 13:08:03 +08:00
    可以使用类型断言,或者是使用别名。 别名的方式是 type I = int, 支持 1.9 以上版本,但有些其它的限制。
    yufpga
        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 三种引用累心,其余都是值类型。
    Leigg
        5
    Leigg  
       2018-07-13 13:53:58 +08:00 via iPhone
    @yufpga 引用类型还包括反射,函数,接口
    Lpl
        6
    Lpl  
       2018-07-13 14:09:50 +08:00
    @Leigg 接口不应该叫引用类型,应该叫指针类型
    hheedat
        7
    hheedat  
    OP
       2018-07-13 15:14:47 +08:00
    @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
    yufpga
        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, 函数类型 ...(欢迎继续补充, 其实这些类型看上去还是挺有规律的)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2101 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:12 · PVG 00:12 · LAX 08:12 · JFK 11:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.