连接池
1 需要注册连接的方法
2 连接必须实现关闭方法
3 运行注册pool
4 是否关闭
5 写连接池和关闭的时候加锁
6 接口的实现是区分*和非*的
具体实现代码
package workpool
import (
"errors"
"io"
"log"
"sync"
)
//创建连接的接口
type createConection interface {
CreateConnect() (io.Closer, error)
}
//一个pool
type ConectPool struct {
closeChan chan io.Closer
factory createConection
isClose bool
mutex sync.Mutex
}
//新建一个pool
func NewConnectPool(poolSize int, factory createConection) (*ConectPool, error) {
if poolSize < 0 {
return nil, errors.New("pool size < 0")
}
return &ConectPool{
closeChan: make(chan io.Closer, poolSize),
factory: factory,
isClose: false,
}, nil
}
//获取连接
func (cp *ConectPool) GetConnect() (io.Closer, error) {
select {
case connect, ok := <-cp.closeChan:
if !ok {
return nil, errors.New("closeChan is closed")
}
log.Println("fetch connect sucessed")
return connect, nil
default:
log.Println("fetch connect faild,create a new one")
return cp.factory.CreateConnect()
}
}
//把一个连接放入池子
func (cp *ConectPool) PutConnect(aConnection io.Closer) {
cp.mutex.Lock()
defer cp.mutex.Unlock()
if cp.isClose == true {
return
}
select {
case cp.closeChan <- aConnection:
log.Println("put connection into the closer!")
default:
log.Println("put faild.close connection!")
aConnection.Close()
}
}
//关闭连接
func (cp *ConectPool) Close() {
cp.mutex.Lock()
defer cp.mutex.Unlock()
if cp.isClose != true {
cp.isClose = true
}
close(cp.closeChan)
for aConnect := range cp.closeChan {
aConnect.Close()
}
}
测试例子
//创建一个connect
var connectId int32 = 0
type DbConnect struct {
cid int32
}
func (db *DbConnect) getConnectId() int32 {
return db.cid
}
func (db *DbConnect) Close() error {
return nil
}
//创建连接
type DbConnectCreater struct{}
func (dbc *DbConnectCreater) CreateConnect() (io.Closer, error) {
id := atomic.AddInt32(&connectId, 1)
return &DbConnect{cid: id}, nil
}
func tpool3() {
fmt.Println("test connect pool3")
creater := &DbConnectCreater{}
pool3, err := workpool.NewConnectPool(10, creater)
if err != nil {
log.Println("create faild")
}
defer pool3.Close()
//放入10个连接
for i := 0; i < 10; i++ {
conect, err := creater.CreateConnect()
if err == nil {
pool3.PutConnect(conect)
}
}
for i := 0; i < 12; i++ {
connect, err := pool3.GetConnect()
if err == nil {
log.Println("connect_id=", connect.(*DbConnect).getConnectId())
}
}
}