https://github.com/panjf2000/ants/blob/master/README_ZH.md



1. 性能测试做的很全面，具体方法总结

2. 接口定义清晰，同时 demo 结合 defer 做资源释放

   2.1. Submit、NewPoolWithFunc、Invoke、Release

   2.2. Options -> WithXXArgOptions

3. 使用文档清晰全面，同时还有运行时流程图

4. 单元测试集中在 ants_test.go 文件，面向应用的行为（接口）在测试



优秀代码片段

1. 自动设置 Pool 是阻塞的还是非阻塞的，防止单核频繁切换 Goroutine 调度：Inspired by fasthttp at https://github.com/valyala/fasthttp/blob/master/workerpool.go#L139

```go
workerChanCap = func() int {
		// Use blocking workerChan if GOMAXPROCS=1.
		// This immediately switches Serve to WorkerFunc, which results
		// in higher performance (under go1.5 at least).
		if runtime.GOMAXPROCS(0) == 1 {
			return 0
		}

		// Use non-blocking workerChan if GOMAXPROCS>1,
		// since otherwise the Serve caller (Acceptor) may lag accepting
		// new connections if WorkerFunc is CPU-bound.
		return 1
	}()
```



2. 使用 atomic 原子操作代替锁，优点是啥？性能更高？

```go
type spinLock uint32

func (sl *spinLock) Lock() {
	for !atomic.CompareAndSwapUint32((*uint32)(sl), 0, 1) {
		runtime.Gosched()
	}
}

func (sl *spinLock) Unlock() {
	atomic.StoreUint32((*uint32)(sl), 0)
}

// NewSpinLock instantiates a spin-lock.
func NewSpinLock() sync.Locker {
	return new(spinLock)
}
```



3. Goroutine 内存提前申请分配，有循环队列和栈两种管理类型

```go
if p.options.PreAlloc {
		p.workers = newWorkerArray(loopQueueType, size)
} else {
		p.workers = newWorkerArray(stackType, 0)
}
```

loopQueueType 循环队列（维护首尾指针）提前分配好了内存，性能高

stackType 是一个可扩展长度的池（slice），每次从队尾获取/插入 Goroutine，节约内存；用二分查找来寻找过期的 Goroutine



4. 使用 sync.Pool 来加速获取在运行的 worker，sync.Pool 是干啥的? 存储运行中的 Goroutine ?

   

5. workerArray 是存储已经申请的 Goroutine （不是在运行中的）进行池化，重复利用？

   5.1. insert 插入空闲 Goroutine 到 workerArray

   5.2. detach 从 workerArray 获取可用的 Goroutine
Add go opensource project reading
Add go opensource project reading
