提交 f8bb58f4 编写于 作者: 写代码的明哥's avatar 写代码的明哥

新增文章

上级 480e7c89
......@@ -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
......
......@@ -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 <https://golang.org/>`__ 项目 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
# 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册