diff --git a/source/c08/c08_01.md b/source/c08/c08_01.md index e5b4d969db612af7b2bfb3209cb28f0fc9d6eb24..bb5ea0b19a72a052c89355bd8281302dd25b7ad0 100644 --- a/source/c08/c08_01.md +++ b/source/c08/c08_01.md @@ -199,7 +199,11 @@ W3Cschool 也是一个专业的编程入门学习及技术文档查询应用, ![](http://image.iswbm.com/20200430175818.png) +### 冰霜之地 +网站链接:https://halfrost.com/tag/golang/ + +![](http://image.iswbm.com/20210901084203.png) ## 4. 工具使用 @@ -243,6 +247,12 @@ Go Walker 是一个可以在线生成并浏览 [Go](https://golang.org/) 项目 ![](http://image.iswbm.com/20200430174109.png) +### A Tour of Go + +通过例子学习 Go 编程,还提高在线运行环境,可以让你通过浏览器就可以直接运行 go 的程序 + +![](http://image.iswbm.com/20210902222745.png) + ## 5. 技术社区 ### GoCN diff --git a/source/c08/c08_01.rst b/source/c08/c08_01.rst index df6bf9d6c9c02df3eb093fdcad0ae579e888cbe6..355fd135346412d6474ce4b9da9b8accc902d270 100644 --- a/source/c08/c08_01.rst +++ b/source/c08/c08_01.rst @@ -226,6 +226,13 @@ Go 语言高级编程 |image16| +冰霜之地 +~~~~~~~~ + +网站链接:https://halfrost.com/tag/golang/ + +|image17| + 4. 工具使用 ----------- @@ -240,7 +247,7 @@ go 的命令非常多,如果想系统的学习,推荐郝林的 Go 命令教 2、https://wiki.jikexueyuan.com/project/go-command-tutorial/0.0.html -|image17| +|image18| Uber 编程规范 ~~~~~~~~~~~~~ @@ -257,7 +264,7 @@ Uber”,也就是 Go 代码应该怎样写、不该怎样写。 中文译文:https://www.infoq.cn/article/G6c95VyU5telNXXCC9yO -|image18| +|image19| Go Walker ~~~~~~~~~ @@ -265,7 +272,7 @@ Go Walker Go Walker 是一个可以在线生成并浏览 `Go `__ 项目 API 文档的 Web 服务器,目前已支持包括 **GitHub** 等代码托管平台。 -|image19| +|image20| CTOLib 码库 ~~~~~~~~~~~ @@ -275,7 +282,15 @@ CTOLib 码库 **网站链接**\ :https://www.ctolib.com/go/categories/go-guide.html -|image20| +|image21| + +A Tour of Go +~~~~~~~~~~~~ + +通过例子学习 Go +编程,还提高在线运行环境,可以让你通过浏览器就可以直接运行 go 的程序 + +|image22| 5. 技术社区 ----------- @@ -285,7 +300,7 @@ GoCN **网站链接**\ :https://gocn.vip/ -|image21| +|image23| Go 语言中文网 ~~~~~~~~~~~~~ @@ -296,7 +311,7 @@ Go历史版本的下载,各种高质量的电子书资源,各种大牛写的 **网站链接**\ :https://studygolang.com/ -|image22| +|image24| 6. 源码学习 ----------- @@ -309,14 +324,14 @@ Go 夜读 **网站链接**\ :https://talkgo.org/ -|image23| +|image25| Go 语言原本 ~~~~~~~~~~~ **网站链接**\ :https://changkun.de/golang/ -|image24| +|image26| Go 语言设计与实现 ~~~~~~~~~~~~~~~~~ @@ -325,14 +340,14 @@ Go 语言设计与实现 **网站链接**\ :https://draveness.me/golang/ -|image25| +|image27| 能翻到这里的,一定是真爱了,本以为 Go 语言还处于不温不火的状态,没想到收集整理一下,资料还挺多的。 -------------- -|image26| +|image28| .. |image0| image:: http://image.iswbm.com/20200607145423.png .. |image1| image:: http://image.iswbm.com/20200430112024.png @@ -351,14 +366,16 @@ Go 语言设计与实现 .. |image14| image:: http://image.iswbm.com/20200430100755.png .. |image15| image:: http://image.iswbm.com/20200430095544.png .. |image16| image:: http://image.iswbm.com/20200430175818.png -.. |image17| image:: http://image.iswbm.com/20200430102821.png -.. |image18| image:: http://image.iswbm.com/20200430113756.png -.. |image19| image:: http://image.iswbm.com/20200430170054.png -.. |image20| image:: http://image.iswbm.com/20200430174109.png -.. |image21| image:: http://image.iswbm.com/20200506192127.png -.. |image22| image:: http://image.iswbm.com/20200430134207.png -.. |image23| image:: http://image.iswbm.com/20200430174216.png -.. |image24| image:: http://image.iswbm.com/20200506191803.png -.. |image25| image:: http://image.iswbm.com/20200506191632.png -.. |image26| image:: http://image.iswbm.com/20200607174235.png +.. |image17| image:: http://image.iswbm.com/20210901084203.png +.. |image18| image:: http://image.iswbm.com/20200430102821.png +.. |image19| image:: http://image.iswbm.com/20200430113756.png +.. |image20| image:: http://image.iswbm.com/20200430170054.png +.. |image21| image:: http://image.iswbm.com/20200430174109.png +.. |image22| image:: http://image.iswbm.com/20210902222745.png +.. |image23| image:: http://image.iswbm.com/20200506192127.png +.. |image24| image:: http://image.iswbm.com/20200430134207.png +.. |image25| image:: http://image.iswbm.com/20200430174216.png +.. |image26| image:: http://image.iswbm.com/20200506191803.png +.. |image27| image:: http://image.iswbm.com/20200506191632.png +.. |image28| image:: http://image.iswbm.com/20200607174235.png diff --git a/source/c08/c08_04.md b/source/c08/c08_04.md new file mode 100644 index 0000000000000000000000000000000000000000..684d8da3788a78ce8c3972d442fcd7eb2202b364 --- /dev/null +++ b/source/c08/c08_04.md @@ -0,0 +1,246 @@ +# 8.4 Go 中晦涩难懂的寻址问题 + +## 什么叫可寻址? + +可直接使用 `&` 操作符取地址的对象,就是可寻址的(Addressable)。比如下面这个例子 + +```go +func main() { + name := "iswbm" + fmt.Println(&name) + // output: 0xc000010200 +} +``` + +程序运行不会报错,说明 name 这个变量是可寻址的。 + +但不能说 `"iswbm"` 这个字符串是可寻址的。 + +`"iswbm"` 是字符串,字符串都是不可变的,是不可寻址的,后面会介绍到。 + +在开始逐个介绍之前,先说一下结论 + +- 指针可以寻址:`&Profile{}` +- 变量可以寻址:`name := Profile{}` +- 字面量通通不能寻址:`Profile{}` + +## 哪些是可以寻址的? + +### 变量:`&x` + +```go +func main() { + name := "iswbm" + fmt.Println(&name) + // output: 0xc000010200 +} +``` + +### 指针:`&*x` + +```go +type Profile struct { + Name string +} + +func main() { + fmt.Println(&Profile{}) + // output: 0xc00000e028 +} +``` + +### 数组元素索引: `&a[0]` + +```go +func main() { + s := [...]int{1,2,3} + fmt.Println(&s[0]) + // output: xc0000b4010 +} +``` + +### 切片 + +```go +func main() { + fmt.Println([]int{1, 2, 3}[1:]) +} +``` + +### 切片元素索引:`&s[1]` + +```go +func main() { + s := make([]int , 2, 2) + fmt.Println(&s[0]) + // output: xc0000b4010 +} +``` + +### 组合字面量: `&struct{ X int }{1}` + +所有的组合字面量都是不可寻址的,就像下面这样子 + +```go +type Profile struct { + Name string +} + +func new() Profile { + return Profile{Name: "iswbm"} +} + +func main() { + fmt.Println(&new()) + // cannot take the address of new() +} +``` + +注意上面写法与这个写法的区别,下面这个写法代表不同意思,其中的 `&` 并不是取地址的操作,而代表实例化一个结构体的指针。 + +```go +type Profile struct { + Name string +} + +func main() { + fmt.Println(&Profile{Name: "iswbm"}) // ok +} +``` + +虽然组合字面量是不可寻址的,但却可以对组合字面量的字段属性进行寻址(直接访问) + +```go +type Profile struct { + Name string +} + +func new() Profile { + return Profile{Name: "iswbm"} +} + +func main() { + fmt.Println(new().Name) +} +``` + +网上有博客说 + +>如果一个结构体值是可寻址的,则它的字段也是可寻址的;反之,一个不可寻址的结构体值的字段也是不可寻址的。 不可寻址的字段的值是不可更改的。所有的组合字面量都是不可寻址的。 + +对于这种说法,我实在无法理解,结构体值(组合字面量)明明是不可寻址的,但为什么其字段可以寻址呢? + +## 哪些是不可以寻址的? + +### 常量 + +```go +import "fmt" + +const VERSION = "1.0" + +func main() { + fmt.Println(&VERSION) +} +``` + +### 字符串 + +```go +func getStr() string { + return "iswbm" +} +func main() { + fmt.Println(&getStr()) + // cannot take the address of getStr() +} +``` + +### 函数或方法 + +```go +func getStr() string { + return "iswbm" +} +func main() { + fmt.Println(&getStr) + // cannot take the address of getStr +} +``` + +### 基本类型字面量 + +字面量分:**基本类型字面量** 和 **复合型字面量**。 + +基本类型字面量,是一个值的文本表示,都是不应该也是不可以被寻址的。 + +```go +func getInt() int { + return 1024 +} + +func main() { + fmt.Println(&getInt()) + // cannot take the address of getInt() +} +``` + +### map 中的元素 + +字典比较特殊,可以从两个角度来反向推导,假设字典的元素是可寻址的,会出现 什么问题? + +1. 如果字典的元素不存在,则返回零值,而零值是不可变对象,如果能寻址问题就大了。 +2. 而如果字典的元素存在,考虑到 Go 中 map 实现中元素的地址是变化的,这意味着寻址的结果也是无意义的。 + +基于这两点,Map 中的元素不可寻址,符合常理。 + +```go +func main() { + p := map[string]string { + "name": "iswbm", + } + + fmt.Println(&p["name"]) + // cannot take the address of p["name"] +} +``` + +搞懂了这点,你应该能够理解下面这段代码为什么会报错啦~ + +```go +package main + +import "fmt" + +type Person struct { + Name string + Email string +} + +func main() { + m := map[int]Person{ + 1:Person{"Andy", "1137291867@qq.com"}, + 2:Person{"Tiny", "qishuai231@gmail.com"}, + 3:Person{"Jack", "qs_edu2009@163.com"}, + } + + //编译错误:cannot assign to struct field m[1].Name in map + m[1].Name = "Scrapup" +``` + +### 数组字面量 + +数组字面量是不可寻址的,当你对数组字面量进行切片操作,其实就是寻找内部元素的地址,下面这段代码是会报错的 + +```go +func main() { + fmt.Println([3]int{1, 2, 3}[1:]) + // invalid operation [3]int literal[1:] (slice of unaddressable value) +} +``` + + + +参考文章: + +- https://gfw.go101.org/article/struct.html \ No newline at end of file