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

更正网友评论区指出的错误字与表述问题

上级 d245c889
......@@ -91,9 +91,9 @@ cannot use "A" (type string) as type byte in assignment
上面我说了,byte 和 uint8 没有区别,rune 和 uint32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
上面我说了,byte 和 uint8 没有区别,rune 和 int32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
理由很简单,因为uint8 和 uint32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。
理由很简单,因为uint8 和 int32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。
......@@ -239,4 +239,3 @@ func main() {
......@@ -96,10 +96,10 @@ Unicode字符(Unicode是一个可以表示世界范围内的绝大部分字符
cannot use "A" (type string) as type byte in assignment
上面我说了,byte 和 uint8 没有区别,rune 和 uint32
上面我说了,byte 和 uint8 没有区别,rune 和 int32
没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
理由很简单,因为uint8 和 uint32
理由很简单,因为uint8 和 int32
,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了
byte 和 rune 这两个别名类型。
......
......@@ -100,7 +100,10 @@ func main() {
}
```
非常抱歉,目前以我的水平,暂时还无法解释这种现象,我建议是单独记忆一下这种特殊场景。
这种现象对于新手来说,确实是个难点,不过这是面试的热点话题,感兴趣的朋友,可以去我的个人博客,查看下面这两篇文章:
- [Go 语言面试题 100 讲之 014篇:说说 Go 中闭包的底层原理?](https://iswbm.com/534.html)
- [Go 语言面试题 100 讲之 015篇:defer 的变量快照什么情况会失效?](https://iswbm.com/535.html)
## 3. 多个defer 反序调用
......
......@@ -106,7 +106,12 @@ defer 的用法很简单,只要在后面跟一个函数的调用,就能实
fmt.Println(name) // 输出: python
}
非常抱歉,目前以我的水平,暂时还无法解释这种现象,我建议是单独记忆一下这种特殊场景。
这种现象对于新手来说,确实是个难点,不过这是面试的热点话题,感兴趣的朋友,可以去我的个人博客,查看下面这两篇文章:
- `Go 语言面试题 100 讲之 014篇:说说 Go
中闭包的底层原理? <https://iswbm.com/534.html>`__
- `Go 语言面试题 100 讲之 015篇:defer
的变量快照什么情况会失效? <https://iswbm.com/535.html>`__
3. 多个defer 反序调用
---------------------
......
......@@ -50,11 +50,11 @@ func main() {
./demo.go:30:10: phone.send_wechat undefined (type Phone has no field or method send_wechat)
```
原因也很明显,因为我们的phone对象显声明为 Phone 接口类型,因此 phone调用的方法会受到此接口的限制。
原因也很明显,因为我们的phone对象显声明为 Phone 接口类型,因此 phone调用的方法会受到此接口的限制。
**那么如何让 phone 可以调用 send_wechat 方法呢?**
答案是可以不显的声明为 Phone接口类型 ,但要清楚 phone 对象实际上是隐式的实现了 Phone 接口,如此一来,方法的调用就不会受到接口类型的约束。
答案是可以不显的声明为 Phone接口类型 ,但要清楚 phone 对象实际上是隐式的实现了 Phone 接口,如此一来,方法的调用就不会受到接口类型的约束。
修改 main 方法成如下
......@@ -144,7 +144,7 @@ func main() {
当你使用这种写法时,Go 会默默地为我们做一件事,就是把传入函数的参数值(注意:Go 语言中的函数调用都是值传递的)的类型隐式的转换成 interface{} 类型。
### 如何进行接口类型的显转换
### 如何进行接口类型的显转换
上面了解了函数中 接口类型的隐式转换后,你的心里可能开始有了疑问了,难道我使用类型断言,只能通过一个接收空接口类型的函数才能实现吗?
......
......@@ -57,12 +57,12 @@ call 函数),一个是发微信(send_wechat 函数)。
# command-line-arguments
./demo.go:30:10: phone.send_wechat undefined (type Phone has no field or method send_wechat)
原因也很明显,因为我们的phone对象显声明为 Phone 接口类型,因此
原因也很明显,因为我们的phone对象显声明为 Phone 接口类型,因此
phone调用的方法会受到此接口的限制。
**那么如何让 phone 可以调用 send_wechat 方法呢?**
答案是可以不显的声明为 Phone接口类型 ,但要清楚 phone
答案是可以不显的声明为 Phone接口类型 ,但要清楚 phone
对象实际上是隐式的实现了 Phone
接口,如此一来,方法的调用就不会受到接口类型的约束。
......@@ -156,7 +156,7 @@ Go 语言中的函数调用都是值传递的,变量会在方法调用前进
会默默地为我们做一件事,就是把传入函数的参数值(注意:Go
语言中的函数调用都是值传递的)的类型隐式的转换成 interface{} 类型。
如何进行接口类型的显转换
如何进行接口类型的显转换
~~~~~~~~~~~~~~~~~~~~~~~~~~
上面了解了函数中
......
......@@ -80,18 +80,18 @@ select 和 pool ,除了解决了连接数的限制 ,其他似乎没有本质
epoll 解决了前期 select 和 poll 出现的一系列的尴尬问题,比如:
- select 和 poll 无差别轮循fd,浪费资源,epool 使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
- select 和 poll 线程不安全,epool 线程安全
- select 请求连接数的限制,epool 能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
- select 和 poll 无差别轮循fd,浪费资源,epoll 使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
- select 和 poll 线程不安全,epoll 线程安全
- select 请求连接数的限制,epoll 能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
- select 和 pool 需要频繁地将fd复制到内核空间,开销大,epoll通过内核和用户空间共享一块内存来减少这方面的开销。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epool,这也不是就说 epool 出现了, select 就会被淘汰掉。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epoll,这也不是就说 epoll 出现了, select 就会被淘汰掉。
epool 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epool 的性能最好。
epoll 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epoll 的性能最好。
而 select 关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择 select 会更好,因为 epool 的通知回调机制需要很多的函数回调。
而 select 关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择 select 会更好,因为 epoll 的通知回调机制需要很多的函数回调。
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epool 是 Linux 所有的,其他平台上没有。
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epoll 是 Linux 所有的,其他平台上没有。
IO多路复用除了以上三种不同的具体实现的区别外,还可以根据线程数的多少来分类
......@@ -159,4 +159,3 @@ https://studygolang.com/articles/13344
......@@ -98,26 +98,26 @@ descriptor),而你要处理一个请求,却要遍历几万个fd,这样
epoll 解决了前期 select 和 poll 出现的一系列的尴尬问题,比如:
- select 和 poll 无差别轮循fd,浪费资源,epool
- select 和 poll 无差别轮循fd,浪费资源,epoll
使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
- select 和 poll 线程不安全,epool 线程安全
- select 请求连接数的限制,epool
- select 和 poll 线程不安全,epoll 线程安全
- select 请求连接数的限制,epoll
能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
- select 和 pool
需要频繁地将fd复制到内核空间,开销大,epoll通过内核和用户空间共享一块内存来减少这方面的开销。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epool,这也不是就说
epool 出现了, select 就会被淘汰掉。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epoll,这也不是就说
epoll 出现了, select 就会被淘汰掉。
epool
关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epool
epoll
关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epoll
的性能最好。
而 select
关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择
select 会更好,因为 epool 的通知回调机制需要很多的函数回调。
select 会更好,因为 epoll 的通知回调机制需要很多的函数回调。
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epool
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epoll
是 Linux 所有的,其他平台上没有。
IO多路复用除了以上三种不同的具体实现的区别外,还可以根据线程数的多少来分类
......
......@@ -291,7 +291,7 @@ func main() {
wg.Add(2)
dataChan := make(chan []byte)
go func() {
wg.Done()
defer wg.Done()
for {
data := make([]byte, 100)
n, _ := syscall.Read(fd, data)
......
......@@ -309,7 +309,7 @@ os 库本质上也是调用 syscall 库,但由于 syscall
wg.Add(2)
dataChan := make(chan []byte)
go func() {
wg.Done()
defer wg.Done()
for {
data := make([]byte, 100)
n, _ := syscall.Read(fd, data)
......
......@@ -116,7 +116,7 @@ http://0.0.0.0:9999
- 本地电脑,就访问:http://localhost:9999
- 服务器,就访问:http://host-ip:9999
然后就可以看到像下面这样的可视化界面,一下子就可能牛二以 main.concat 的区域最大
然后就可以看到像下面这样的可视化界面,一下子就可以看出 main.concat 的区域最大
![](http://image.iswbm.com/20220119150344.png)
......
......@@ -127,7 +127,7 @@ pprof <https://darjun.github.io/2021/06/09/youdontknowgo/pprof/>`__\ ,写得
- 本地电脑,就访问:http://localhost:9999
- 服务器,就访问:http://host-ip:9999
然后就可以看到像下面这样的可视化界面,一下子就可能牛二以 main.concat
然后就可以看到像下面这样的可视化界面,一下子就可以看出 main.concat
的区域最大
.. image:: http://image.iswbm.com/20220119150344.png
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册