首页 > 代码库 > golang 创建一个简单的资源池,重用资源,减少GC负担

golang 创建一个简单的资源池,重用资源,减少GC负担

package main;import (	"sync"	"errors"	"fmt")//代码参考《Go语言实战》中第7章并发模式Pool//如果哪个类型实现了Resource接口中的两个方法,我们就认为该类型是资源type Resource interface {	Close();	IsClosed() bool;}//工厂方法,用于创建新资源type Factory func() (Resource, error)//资源池type ResourcePool struct {	//互斥锁,保证池中资源的安全	mu sync.Mutex;	//通道,用于保存资源	res chan Resource;	//工厂方法	factory Factory;	//判断资源池是否关闭	closed bool;}//创建一个资源池func NewResourcePool(factory Factory, cap int) (*ResourcePool, error) {	if cap > 0 {		return &ResourcePool{			mu:      sync.Mutex{},			res:     make(chan Resource, cap),			factory: factory,			closed:  false,		}, nil;	}	return nil, errors.New("cap应大于0");}//从资源池中获取一个资源func (rp *ResourcePool) Get() (Resource, error) {	if rp.closed {		return nil, errors.New("资源池已关闭");	}	select {	//获取资源,判断通道是否关闭	case item, ok := <-rp.res:		{			if !ok {				return nil, errors.New("资源池已关闭");			}			return item, nil;		}	default:		{			//返回工厂创建的资源			return rp.factory();		}	}}//将资源放入池中func (rp *ResourcePool) Put(res Resource) error {	if rp.closed {		return errors.New("资源池已关闭");	}	select {	//当res无法插入时,这里会阻塞,select执行default	case rp.res <- res:		{			return nil;		}	default:		{			res.Close();			return errors.New("资源池已满");		}	}}//关闭资源池func (rp *ResourcePool) Close() {	if rp.closed {		return;	}	rp.mu.Lock();	//关闭资源池	rp.closed = true;	//关闭通道,不在往通道中添加新资源	close(rp.res);	//循环关闭通道中的资源	for item := range rp.res {		if !item.IsClosed() {			item.Close();		}	}	rp.mu.Unlock();}//自定义一个资源类型type Data struct {	data []byte;}func (d Data) Close() {	d.data = nil;}func (d Data) IsClosed() bool {	if len(d.data) > 0 {		return true;	} else {		return false;	}}func (d Data) Write(b []byte) {	copy(d.data, b);}func main() {	//创建一个资源池	pool, _ := NewResourcePool(func() (Resource, error) {		return Data{			data: make([]byte, 16),		}, nil;	}, 3);	//获取资源	item1, _ := pool.Get();	item1.(Data).Write([]byte("123"));	item2, _ := pool.Get();	item2.(Data).Write([]byte("456"));	item3, _ := pool.Get();	item3.(Data).Write([]byte("789"));	fmt.Println(item1);	fmt.Println(item2);	fmt.Println(item3);	//我们再获取一个资源	item4, _ := pool.Get();	//我们把源资入回池中	pool.Put(item1);	pool.Put(item2);	pool.Put(item3);	//这里就会报错了,因为我们创建池时,设置的大小为3	err := pool.Put(item4);	if err != nil {		fmt.Println(err);	}	//关闭资源池	pool.Close();}

  

golang 创建一个简单的资源池,重用资源,减少GC负担