Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
go开源项目镜像
GolangCodingTime
提交
b5cf7664
G
GolangCodingTime
项目概览
go开源项目镜像
/
GolangCodingTime
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
GolangCodingTime
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
b5cf7664
编写于
6月 11, 2022
作者:
写代码的明哥
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
更正网友评论区指出的错误字与表述问题
上级
d245c889
变更
12
隐藏空白更改
内联
并排
Showing
12 changed file
with
40 addition
and
34 deletion
+40
-34
source/c01/c01_04.md
source/c01/c01_04.md
+2
-3
source/c01/c01_04.rst
source/c01/c01_04.rst
+2
-2
source/c01/c01_12.md
source/c01/c01_12.md
+4
-1
source/c01/c01_12.rst
source/c01/c01_12.rst
+6
-1
source/c02/c02_06.md
source/c02/c02_06.md
+3
-3
source/c02/c02_06.rst
source/c02/c02_06.rst
+3
-3
source/c04/c04_11.md
source/c04/c04_11.md
+7
-8
source/c04/c04_11.rst
source/c04/c04_11.rst
+9
-9
source/c05/c05_04.md
source/c05/c05_04.md
+1
-1
source/c05/c05_04.rst
source/c05/c05_04.rst
+1
-1
source/c06/c06_05.md
source/c06/c06_05.md
+1
-1
source/c06/c06_05.rst
source/c06/c06_05.rst
+1
-1
未找到文件。
source/c01/c01_04.md
浏览文件 @
b5cf7664
...
...
@@ -91,9 +91,9 @@ cannot use "A" (type string) as type byte in assignment
上面我说了,byte 和 uint8 没有区别,rune 和
u
int32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
上面我说了,byte 和 uint8 没有区别,rune 和 int32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
理由很简单,因为uint8 和
u
int32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。
理由很简单,因为uint8 和 int32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。
...
...
@@ -239,4 +239,3 @@ func main() {
source/c01/c01_04.rst
浏览文件 @
b5cf7664
...
...
@@ -96,10 +96,10 @@ Unicode字符(Unicode是一个可以表示世界范围内的绝大部分字符
cannot use "A" (type string) as type byte in assignment
上面我说了,byte 和 uint8 没有区别,rune 和
u
int32
上面我说了,byte 和 uint8 没有区别,rune 和 int32
没有区别,那为什么还要多出一个 byte 和 rune 类型呢?
理由很简单,因为uint8 和
u
int32
理由很简单,因为uint8 和 int32
,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了
byte 和 rune 这两个别名类型。
...
...
source/c01/c01_12.md
浏览文件 @
b5cf7664
...
...
@@ -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 反序调用
...
...
source/c01/c01_12.rst
浏览文件 @
b5cf7664
...
...
@@ -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
反序调用
---------------------
...
...
source/c02/c02_06.md
浏览文件 @
b5cf7664
...
...
@@ -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{} 类型。
### 如何进行接口类型的显
示
转换
### 如何进行接口类型的显
式
转换
上面了解了函数中 接口类型的隐式转换后,你的心里可能开始有了疑问了,难道我使用类型断言,只能通过一个接收空接口类型的函数才能实现吗?
...
...
source/c02/c02_06.rst
浏览文件 @
b5cf7664
...
...
@@ -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
{}
类型。
如何进行接口类型的显
示
转换
如何进行接口类型的显
式
转换
~~~~~~~~~~~~~~~~~~~~~~~~~~
上面了解了函数中
...
...
source/c04/c04_11.md
浏览文件 @
b5cf7664
...
...
@@ -80,18 +80,18 @@ select 和 pool ,除了解决了连接数的限制 ,其他似乎没有本质
epoll 解决了前期 select 和 poll 出现的一系列的尴尬问题,比如:
-
select 和 poll 无差别轮循fd,浪费资源,epo
o
l 使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
-
select 和 poll 线程不安全,epo
o
l 线程安全
-
select 请求连接数的限制,epo
o
l 能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
-
select 和 poll 无差别轮循fd,浪费资源,epo
l
l 使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
-
select 和 poll 线程不安全,epo
l
l 线程安全
-
select 请求连接数的限制,epo
l
l 能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
-
select 和 pool 需要频繁地将fd复制到内核空间,开销大,epoll通过内核和用户空间共享一块内存来减少这方面的开销。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epo
ol,这也不是就说 epoo
l 出现了, select 就会被淘汰掉。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epo
ll,这也不是就说 epol
l 出现了, select 就会被淘汰掉。
epo
ol 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epoo
l 的性能最好。
epo
ll 关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epol
l 的性能最好。
而 select 关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择 select 会更好,因为 epo
o
l 的通知回调机制需要很多的函数回调。
而 select 关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择 select 会更好,因为 epo
l
l 的通知回调机制需要很多的函数回调。
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epo
o
l 是 Linux 所有的,其他平台上没有。
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epo
l
l 是 Linux 所有的,其他平台上没有。
IO多路复用除了以上三种不同的具体实现的区别外,还可以根据线程数的多少来分类
...
...
@@ -159,4 +159,3 @@ https://studygolang.com/articles/13344
source/c04/c04_11.rst
浏览文件 @
b5cf7664
...
...
@@ -98,26 +98,26 @@ descriptor),而你要处理一个请求,却要遍历几万个fd,这样
epoll 解决了前期 select 和 poll 出现的一系列的尴尬问题,比如:
- select 和 poll 无差别轮循fd,浪费资源,epo
o
l
- select 和 poll 无差别轮循fd,浪费资源,epo
l
l
使用通知回调机制,有流发生 IO事件时就会主动触发回调函数
- select 和 poll 线程不安全,epo
o
l 线程安全
- select 请求连接数的限制,epo
o
l
- select 和 poll 线程不安全,epo
l
l 线程安全
- select 请求连接数的限制,epo
l
l
能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)
- select 和 pool
需要频繁地将fd复制到内核空间,开销大,epoll通过内核和用户空间共享一块内存来减少这方面的开销。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epo
o
l,这也不是就说
epo
o
l 出现了, select 就会被淘汰掉。
虽然 I/O 多路复用经历了三种实现:select -> pool -> epo
l
l,这也不是就说
epo
l
l 出现了, select 就会被淘汰掉。
epo
o
l
关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epo
o
l
epo
l
l
关注的是活跃的连接数,当连接数非常多但活跃连接少的情况下(比如长连接数较多),epo
l
l
的性能最好。
而 select
关注的是连接总数,当连接数多而且大部分的连接都很活跃的情况下,选择
select 会更好,因为 epo
o
l 的通知回调机制需要很多的函数回调。
select 会更好,因为 epo
l
l 的通知回调机制需要很多的函数回调。
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epo
o
l
另外还有一点是,select 是 POSIX 规定的,一般操作系统均有实现,而 epo
l
l
是 Linux 所有的,其他平台上没有。
IO多路复用除了以上三种不同的具体实现的区别外,还可以根据线程数的多少来分类
...
...
source/c05/c05_04.md
浏览文件 @
b5cf7664
...
...
@@ -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
)
...
...
source/c05/c05_04.rst
浏览文件 @
b5cf7664
...
...
@@ -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
)
...
...
source/c06/c06_05.md
浏览文件 @
b5cf7664
...
...
@@ -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
)
...
...
source/c06/c06_05.rst
浏览文件 @
b5cf7664
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录