【Golang】sync.Pool对象的复用之切片复用

场景

从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)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值