场景
从channel中读取一批数据,放到切片中,我再进行批量的操作。例如,我从MQ中读取一批数据放入切片,当里面存入5条,形成INSERT或UPDATE语句,整体一次性执行,可以提高数据库连接的使用率。
代码设计
func main() {
ch := make(chan int64)
go func() {
var c int64 = 0
for {
atomic.AddInt64(&c, 1)
ch <- c
time.Sleep(500 * time.Millisecond)
}
}()
var count int64 = 0
var list = NewSlicePool()
sliceList := list.Get()
for data := range ch {
//fmt.Println("开始接收积分消息 ========》")
atomic.AddInt64(&count, 1)
sliceList = append(sliceList, data)
if atomic.LoadInt64(&count)%5 == 0 {
fmt.Printf("执行你自己的逻辑: %v, 切片地址为:%p \n", sliceList, sliceList)
// 重置切片
sliceList = sliceList[:0]
fmt.Printf("重置切片后的内容: %v, 切片地址为:%p \n", list.Get(), sliceList)
// 计数器重置为0
atomic.StoreInt64(&count, 0)
}
}
}
type SlicePool struct {
pool sync.Pool
}
func NewSlicePool() *SlicePool {
return &SlicePool{
pool: sync.Pool{
New: func() interface{} {
return make([]int64, 0)
},
},
}
}
func (p *SlicePool) Get() []int64 {
return p.pool.Get().([]int64)
}
代码运行
代码运行效果如下:
执行你自己的逻辑: [1 2 3 4 5], 切片地址为:0xc0000ec140
重置切片后的内容: [], 切片地址为:0xc0000ec140
执行你自己的逻辑: [6 7 8 9 10], 切片地址为:0xc0000ec140
重置切片后的内容: [], 切片地址为:0xc0000ec140
执行你自己的逻辑: [11 12 13 14 15], 切片地址为:0xc0000ec140
Debugger finished with the exit code 0
可以看到, 切片每次以五个一组的去输出, 并且每次使用的切片都是指向同一个地址
补充
上面的代码可能存在问题,存在多协程竞争读写这个切片,需要加锁
func main() {
ch := make(chan int64)
go func() {
var c int64 = 0
for {
atomic.AddInt64(&c, 1)
ch <- c
time.Sleep(500 * time.Millisecond)
}
}()
var count int64 = 0
var list = NewSlicePool()
sliceList := list.Get()
var mutex sync.Mutex
for data := range ch {
mutex.Lock()
atomic.AddInt64(&count, 1)
sliceList = append(sliceList, data)
if atomic.LoadInt64(&count)%5 == 0 {
fmt.Printf("执行你自己的逻辑: %v, 切片地址为:%p \n", sliceList, sliceList)
go func(list *SlicePool) {
mutex.Lock()
defer mutex.Unlock()
// 重置切片
sliceList = sliceList[:0]
fmt.Printf("重置切片后的内容: %v, 切片地址为:%p \n", list.Get(), sliceList)
// 计数器重置为0
atomic.StoreInt64(&count, 0)
}(list)
}
mutex.Unlock()
}
}
type SlicePool struct {
pool sync.Pool
}
func NewSlicePool() *SlicePool {
return &SlicePool{
pool: sync.Pool{
New: func() interface{} {
return make([]int64, 0)
},
},
}
}
func (p *SlicePool) Get() []int64 {
return p.pool.Get().([]int64)
}