File tree 12 files changed +40
-34
lines changed
12 files changed +40
-34
lines changed Original file line number Diff line number Diff line change @@ -91,9 +91,9 @@ cannot use "A" (type string) as type byte in assignment
91
91
92
92
93
93
94
- 上面我说了,byte 和 uint8 没有区别,rune 和 uint32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
94
+ 上面我说了,byte 和 uint8 没有区别,rune 和 int32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
95
95
96
- 理由很简单,因为uint8 和 uint32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。
96
+ 理由很简单,因为uint8 和 int32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。
97
97
98
98
99
99
@@ -239,4 +239,3 @@ func main() {
239
239
240
240
241
241
242
-
Original file line number Diff line number Diff line change @@ -96,10 +96,10 @@ Unicode字符(Unicode是一个可以表示世界范围内的绝大部分字符
96
96
97
97
cannot use "A" (type string) as type byte in assignment
98
98
99
- 上面我说了,byte 和 uint8 没有区别,rune 和 uint32
99
+ 上面我说了,byte 和 uint8 没有区别,rune 和 int32
100
100
没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
101
101
102
- 理由很简单,因为uint8 和 uint32
102
+ 理由很简单,因为uint8 和 int32
103
103
,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了
104
104
byte 和 rune 这两个别名类型。
105
105
Original file line number Diff line number Diff line change @@ -100,7 +100,10 @@ func main() {
100
100
}
101
101
```
102
102
103
- 非常抱歉,目前以我的水平,暂时还无法解释这种现象,我建议是单独记忆一下这种特殊场景。
103
+ 这种现象对于新手来说,确实是个难点,不过这是面试的热点话题,感兴趣的朋友,可以去我的个人博客,查看下面这两篇文章:
104
+
105
+ - [ Go 语言面试题 100 讲之 014篇:说说 Go 中闭包的底层原理?] ( https://iswbm.com/534.html )
106
+ - [ Go 语言面试题 100 讲之 015篇:defer 的变量快照什么情况会失效?] ( https://iswbm.com/535.html )
104
107
105
108
## 3. 多个defer 反序调用
106
109
Original file line number Diff line number Diff line change @@ -106,7 +106,12 @@ defer 的用法很简单,只要在后面跟一个函数的调用,就能实
106
106
fmt.Println(name) // 输出: python
107
107
}
108
108
109
- 非常抱歉,目前以我的水平,暂时还无法解释这种现象,我建议是单独记忆一下这种特殊场景。
109
+ 这种现象对于新手来说,确实是个难点,不过这是面试的热点话题,感兴趣的朋友,可以去我的个人博客,查看下面这两篇文章:
110
+
111
+ - `Go 语言面试题 100 讲之 014篇:说说 Go
112
+ 中闭包的底层原理? <https://iswbm.com/534.html> `__
113
+ - `Go 语言面试题 100 讲之 015篇:defer
114
+ 的变量快照什么情况会失效? <https://iswbm.com/535.html> `__
110
115
111
116
3. 多个defer 反序调用
112
117
---------------------
Original file line number Diff line number Diff line change @@ -50,11 +50,11 @@ func main() {
50
50
./demo.go :30 :10 : phone.send_wechat undefined (type Phone has no field or method send_wechat)
51
51
```
52
52
53
- 原因也很明显,因为我们的phone对象显示声明为 Phone 接口类型,因此 phone调用的方法会受到此接口的限制。
53
+ 原因也很明显,因为我们的phone对象显式声明为 Phone 接口类型,因此 phone调用的方法会受到此接口的限制。
54
54
55
55
** 那么如何让 phone 可以调用 send_wechat 方法呢?**
56
56
57
- 答案是可以不显示的声明为 Phone接口类型 ,但要清楚 phone 对象实际上是隐式的实现了 Phone 接口,如此一来,方法的调用就不会受到接口类型的约束。
57
+ 答案是可以不显式的声明为 Phone接口类型 ,但要清楚 phone 对象实际上是隐式的实现了 Phone 接口,如此一来,方法的调用就不会受到接口类型的约束。
58
58
59
59
修改 main 方法成如下
60
60
@@ -144,7 +144,7 @@ func main() {
144
144
145
145
当你使用这种写法时,Go 会默默地为我们做一件事,就是把传入函数的参数值(注意:Go 语言中的函数调用都是值传递的)的类型隐式的转换成 interface{} 类型。
146
146
147
- ### 如何进行接口类型的显示转换
147
+ ### 如何进行接口类型的显式转换
148
148
149
149
上面了解了函数中 接口类型的隐式转换后,你的心里可能开始有了疑问了,难道我使用类型断言,只能通过一个接收空接口类型的函数才能实现吗?
150
150
Original file line number Diff line number Diff line change @@ -57,12 +57,12 @@ call 函数),一个是发微信(send_wechat 函数)。
57
57
# command-line-arguments
58
58
./demo.go:30:10: phone.send_wechat undefined (type Phone has no field or method send_wechat)
59
59
60
- 原因也很明显,因为我们的phone对象显示声明为 Phone 接口类型,因此
60
+ 原因也很明显,因为我们的phone对象显式声明为 Phone 接口类型,因此
61
61
phone调用的方法会受到此接口的限制。
62
62
63
63
**那么如何让 phone 可以调用 send_wechat 方法呢? **
64
64
65
- 答案是可以不显示的声明为 Phone接口类型 ,但要清楚 phone
65
+ 答案是可以不显式的声明为 Phone接口类型 ,但要清楚 phone
66
66
对象实际上是隐式的实现了 Phone
67
67
接口,如此一来,方法的调用就不会受到接口类型的约束。
68
68
@@ -156,7 +156,7 @@ Go 语言中的函数调用都是值传递的,变量会在方法调用前进
156
156
会默默地为我们做一件事,就是把传入函数的参数值(注意:Go
157
157
语言中的函数调用都是值传递的)的类型隐式的转换成 interface{} 类型。
158
158
159
- 如何进行接口类型的显示转换
159
+ 如何进行接口类型的显式转换
160
160
~~~~~~~~~~~~~~~~~~~~~~~~~~
161
161
162
162
上面了解了函数中
Original file line number Diff line number Diff line change @@ -80,18 +80,18 @@ select 和 pool ,除了解决了连接数的限制 ,其他似乎没有本质
80
80
81
81
epoll 解决了前期 select 和 poll 出现的一系列的尴尬问题,比如:
82
82
83
- - select 和 poll 无差别轮循fd,浪费资源,epool 使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
84
- - select 和 poll 线程不安全,epool 线程安全
85
- - select 请求连接数的限制,epool 能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
83
+ - select 和 poll 无差别轮循fd,浪费资源,epoll 使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
84
+ - select 和 poll 线程不安全,epoll 线程安全
85
+ - select 请求连接数的限制,epoll 能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
86
86
- select 和 pool 需要频繁地将fd复制到内核空间,开销大,epoll通过内核和用户空间共享一块内存来减少这方面的开销。
87
87
88
- 虽然 I/O 多路复用经历了三种实现:select -> pool -> epool ,这也不是就说 epool 出现了, select 就会被淘汰掉。
88
+ 虽然 I/O 多路复用经历了三种实现:select -> pool -> epoll ,这也不是就说 epoll 出现了, select 就会被淘汰掉。
89
89
90
- epool 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epool 的性能最好。
90
+ epoll 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epoll 的性能最好。
91
91
92
- 而 select 关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择 select 会更好,因为 epool 的通知回调机制需要很多的函数回调。
92
+ 而 select 关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择 select 会更好,因为 epoll 的通知回调机制需要很多的函数回调。
93
93
94
- 另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epool 是 Linux 所有的,其他平台上没有。
94
+ 另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epoll 是 Linux 所有的,其他平台上没有。
95
95
96
96
IO多路复用除了以上三种不同的具体实现的区别外,还可以根据线程数的多少来分类
97
97
@@ -159,4 +159,3 @@ https://studygolang.com/articles/13344
159
159
160
160
161
161
162
-
Original file line number Diff line number Diff line change @@ -98,26 +98,26 @@ descriptor),而你要处理一个请求,却要遍历几万个fd,这样
98
98
99
99
epoll 解决了前期 select 和 poll 出现的一系列的尴尬问题,比如:
100
100
101
- - select 和 poll 无差别轮循fd,浪费资源,epool
101
+ - select 和 poll 无差别轮循fd,浪费资源,epoll
102
102
使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
103
- - select 和 poll 线程不安全,epool 线程安全
104
- - select 请求连接数的限制,epool
103
+ - select 和 poll 线程不安全,epoll 线程安全
104
+ - select 请求连接数的限制,epoll
105
105
能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
106
106
- select 和 pool
107
107
需要频繁地将fd复制到内核空间,开销大,epoll通过内核和用户空间共享一块内存来减少这方面的开销。
108
108
109
- 虽然 I/O 多路复用经历了三种实现:select -> pool -> epool ,这也不是就说
110
- epool 出现了, select 就会被淘汰掉。
109
+ 虽然 I/O 多路复用经历了三种实现:select -> pool -> epoll ,这也不是就说
110
+ epoll 出现了, select 就会被淘汰掉。
111
111
112
- epool
113
- 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epool
112
+ epoll
113
+ 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epoll
114
114
的性能最好。
115
115
116
116
而 select
117
117
关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择
118
- select 会更好,因为 epool 的通知回调机制需要很多的函数回调。
118
+ select 会更好,因为 epoll 的通知回调机制需要很多的函数回调。
119
119
120
- 另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epool
120
+ 另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epoll
121
121
是 Linux 所有的,其他平台上没有。
122
122
123
123
IO多路复用除了以上三种不同的具体实现的区别外,还可以根据线程数的多少来分类
Original file line number Diff line number Diff line change @@ -291,7 +291,7 @@ func main() {
291
291
wg.Add (2 )
292
292
dataChan := make (chan []byte )
293
293
go func () {
294
- wg.Done ()
294
+ defer wg.Done ()
295
295
for {
296
296
data := make ([]byte , 100 )
297
297
n , _ := syscall.Read (fd, data)
Original file line number Diff line number Diff line change @@ -309,7 +309,7 @@ os 库本质上也是调用 syscall 库,但由于 syscall
309
309
wg.Add(2)
310
310
dataChan := make(chan []byte)
311
311
go func() {
312
- wg.Done()
312
+ defer wg.Done()
313
313
for {
314
314
data := make([]byte, 100)
315
315
n, _ := syscall.Read(fd, data)
Original file line number Diff line number Diff line change @@ -116,7 +116,7 @@ http://0.0.0.0:9999
116
116
- 本地电脑,就访问:http://localhost:9999
117
117
- 服务器,就访问:http://host-ip:9999
118
118
119
- 然后就可以看到像下面这样的可视化界面,一下子就可能牛二以 main.concat 的区域最大
119
+ 然后就可以看到像下面这样的可视化界面,一下子就可以看出 main.concat 的区域最大
120
120
121
121
![ ] ( http://image.iswbm.com/20220119150344.png )
122
122
Original file line number Diff line number Diff line change @@ -127,7 +127,7 @@ pprof <https://darjun.github.io/2021/06/09/youdontknowgo/pprof/>`__\ ,写得
127
127
- 本地电脑,就访问:http://localhost:9999
128
128
- 服务器,就访问:http://host-ip:9999
129
129
130
- 然后就可以看到像下面这样的可视化界面,一下子就可能牛二以 main.concat
130
+ 然后就可以看到像下面这样的可视化界面,一下子就可以看出 main.concat
131
131
的区域最大
132
132
133
133
.. image :: http://image.iswbm.com/20220119150344.png
You can’t perform that action at this time.
0 commit comments