diff --git a/chapter01/01.2.md b/chapter01/01.2.md index 1fd95c1..7121825 100644 --- a/chapter01/01.2.md +++ b/chapter01/01.2.md @@ -8,7 +8,7 @@ 有时候我们需要传递一个io.ReadCloser的实例,而我们现在有一个io.Reader的实例,比如:strings.Reader,这个时候NopCloser就派上用场了。它包装一个io.Reader,返回一个io.ReadCloser,而相应的Close方法啥也不做,只是返回nil。 -比如,在标准库net/http包中的NewRequest,接收一个io.Reader的body,而实际上,Request的Body类型的是io.ReadCloser,因此,代码内部进行了判断,如果传递的io.Reader也实现了io.ReadCloser接口,则转换,否则通过ioutil.NoCloser包装转换一下。相关代码如下: +比如,在标准库net/http包中的NewRequest,接收一个io.Reader的body,而实际上,Request的Body的类型是io.ReadCloser,因此,代码内部进行了判断,如果传递的io.Reader也实现了io.ReadCloser接口,则转换,否则通过ioutil.NoCloser包装转换一下。相关代码如下: rc, ok := body.(io.ReadCloser) if !ok && body != nil { diff --git a/chapter16/16.01.md b/chapter16/16.01.md index 5e3d4d8..34f6a35 100644 --- a/chapter16/16.01.md +++ b/chapter16/16.01.md @@ -118,6 +118,31 @@ func (ss *ServerList) PickServer(key string) (net.Addr, error) { 答案是不会的,sync.Pool的回收是有的,它是在系统自动GC的时候,触发pool.go中的poolCleanup函数。 +```golang +func poolCleanup() { + for i, p := range allPools { + allPools[i] = nil + for i := 0; i < int(p.localSize); i++ { + l := indexLocal(p.local, i) + l.private = nil + for j := range l.shared { + l.shared[j] = nil + } + l.shared = nil + } + p.local = nil + p.localSize = 0 + } + allPools = []*Pool{} +} +``` + +这个函数会把Pool中所有goroutine创建的对象都进行销毁。 + +那这里另外一个问题也凸显出来了,很可能我上一步刚往pool中PUT一个对象之后,下一步GC触发,导致pool的GET函数获取不到PUT进去的对象。 +这个时候,GET函数就会调用New函数,临时创建出一个对象,并存放到pool中。 + +根据以上结论,sync.Pool其实不适合用来做持久保存的对象池(比如连接池)。它更适合用来做临时对象池,目的是为了降低GC的压力。 连接池性能测试 @@ -165,30 +190,6 @@ ok _/E_/MyGo/sync 3.345s ``` 通过性能测试可以清楚地看到,使用连接池消耗的CPU时间远远小于每次手动分配内存。 -```golang -func poolCleanup() { - for i, p := range allPools { - allPools[i] = nil - for i := 0; i < int(p.localSize); i++ { - l := indexLocal(p.local, i) - l.private = nil - for j := range l.shared { - l.shared[j] = nil - } - l.shared = nil - } - p.local = nil - p.localSize = 0 - } - allPools = []*Pool{} -} -``` -这个函数会把Pool中所有goroutine创建的对象都进行销毁。 - -那这里另外一个问题也凸显出来了,很可能我上一步刚往pool中PUT一个对象之后,下一步GC触发,导致pool的GET函数获取不到PUT进去的对象。 -这个时候,GET函数就会调用New函数,临时创建出一个对象,并存放到pool中。 - -根据以上结论,sync.Pool其实不适合用来做持久保存的对象池(比如连接池)。它更适合用来做临时对象池,目的是为了降低GC的压力。 ## Once ## diff --git a/preface.md b/preface.md index c2835de..6905261 100644 --- a/preface.md +++ b/preface.md @@ -38,7 +38,6 @@ - 8.5 archive/zip — zip归档访问 * 第九章 [测试](chapter09/09.0.md) - 9.1 [testing - 测试基本使用接口](chapter09/09.1.md) -* 第九章 加解密 * 第十章 进程、线程与goroutine * 第十一章 网络通信与互联网(internet) * 第十二章 email @@ -48,5 +47,6 @@ - 15.1 buildin - 15.2 [unsafe — 非类型安全操作](chapter15/15.02.md) * 第十六章 同步 - - 15.1 [sync - 处理同步需求](chapter16/16.01.md) - - 15.2 [sync/atomic - 原子操作](chapter16/16.02.md) + - 16.1 [sync - 处理同步需求](chapter16/16.01.md) + - 16.2 [sync/atomic - 原子操作](chapter16/16.02.md) +* 第十七章 加解密 \ No newline at end of file