Go 为什么常量、字符串和字典不可寻址?详解

常量

首先要明白一件事,什么叫不可寻址?它指的是,不能通过 & 来获得内存地址的行为。

以常量为例

import "fmt"

const VERSION  = "1.0"

func main() {
    fmt.Println(&VERSION)
}

编译的时候会直接报错说:无法取得 VERSION 的地址。因为它是常量

$ go build main.go
# command-line-arguments
./main.go:8:14: cannot take the address of VERSION

这其实还挺容易理解的,如果常量可以寻址的话,我们就可以通过指针修改常数的值,这无疑破坏了常数的定义。

字典

那么字典里的元素呢?为什么它不可以寻址?

func main() {
    p := map[string]string {
        "name": "iswbm",
    }

    fmt.Println(&p["name"])
    // cannot take the address of p["name"]
}

它比较特殊,可以从两个角度来反向推导,假设字典的元素是可寻址的,会出现什么问题呢?

字典的使用无非两种情况,我们分别来探讨一下

  1. 如果字典的元素不存在,则返回零值,而零值是不可变对象,这种情况要可寻址就有问题了
  2. 而如果字典的元素存在,考虑到 Go 中 map 实现中元素的地址是变化的,前一秒 key1 对应 value1 ,下一秒可能就对应 value2 了,你取其地址,不一定能对应更改到 map 中 key1 的值,这意味着寻址的结果也是无意义的。

基于这两点,Map 中的元素不可寻址,符合常理。

字符串中的字节或者字符

字符串是不可变的,你想要修改其中某个字符,是做不到的。

func main() {
    name := "iswbm"
    name[0] = 'x'  //  can not assign to name[0]
}

因此字符串的字节或者字符不可寻址,没有问题。

注意区分如下这种写法

name = "golang" 只是将 name 指向了一个新的内存地址,这个新的内存地址存的是值是 golang,实际上你并没有改变原字符串 iswbm 的内存地址里存储的值。

func main() {
    name := "iswbm"
    name = "golang"
    fmt.Println(name)
}

教程来源于Github,感谢iswbm大佬的无私奉献,致敬!

技术教程推荐

人工智能基础课 -〔王天一〕

推荐系统三十六式 -〔刑无刀〕

程序员的数学基础课 -〔黄申〕

玩转Git三剑客 -〔苏玲〕

iOS开发高手课 -〔戴铭〕

全栈工程师修炼指南 -〔熊燚(四火)〕

现代C++编程实战 -〔吴咏炜〕

跟着高手学复盘 -〔张鹏〕

B端体验设计入门课 -〔林远宏(汤圆)〕