Golang语言社区--golang通用连接池的实现

golang的channel除了goroutine通信之外还有很多其他的功能,本文将实现一种基于channel的通用连接池。
何为通用?
连接池的实现不依赖具体的实例,而依赖某个接口,本文的连接池选用的是io.Closer接口,只要是实现了该接口的对象都可以被池管理。
当然,你可以实现基于interface{}的连接池,这样任何对象都可以被管理。
实现原理
将连接句柄存入channel中,由于缓存channel的特性,获取连接时如果池中有连接,将直接返回,如果池中没有连接,将阻塞或者新建连接(没超过最大限制的情况下)。
由于面向接口编程,所有创建连接的逻辑是不清楚的,这里需要传入一个函数,该函数返回一个io.Closer对象。
实现
由于并发问题,在需要操作池中互斥数据的时候需要加锁。
  1. package pool

  2. import (
  3. "errors"
  4. "io"
  5. "sync"
  6. "time"
  7. )
  8. var (
  9. ErrInvalidConfig = errors.New("invalid pool config")
  10. ErrPoolClosed = errors.New("pool closed")
  11. type factory func() (io.Closer,error)
  12. type Pool interface {
  13. Acquire() (io.Closer,error) // 获取资源
  14. Release(io.Closer) error // 释放资源
  15. Close(io.Closer) error // 关闭资源
  16. Shutdown() error // 关闭
  17. }
  18. type GenericPool struct {
  19. sync.Mutex
  20. pool chan io.Closer
  21. maxOpen int// 池中最大资源数
  22. numOpen int// 当前池中资源数
  23. minopen int// 池中最少资源数
  24. closed bool // 池是否已关闭
  25. maxLifetime time.Duration
  26. factory factory // 创建连接的方法
  27. func NewGenericPool(minopen,maxOpen int,maxLifetime time.Duration,factory factory) (*GenericPool,error) {
  28. if maxOpen <= 0 || minopen > maxOpen {
  29. return nil,ErrInvalidConfig
  30. }
  31. p := &GenericPool{
  32. maxOpen: maxOpen,
  33. minopen: minopen,serif;font-size:12px;line-height:1.8em;"> maxLifetime: maxLifetime,serif;font-size:12px;line-height:1.8em;"> factory: factory,serif;font-size:12px;line-height:1.8em;"> pool: make(chan io.Closer,maxOpen),serif;font-size:12px;line-height:1.8em;"> for i := 0; i < minopen; i++ {
  34. closer,err := factory()
  35. if err != nil {
  36. continue
  37. p.numOpen++
  38. p.pool <- closer
  39. return p,nil
  40. func (p *GenericPool) Acquire() (io.Closer,serif;font-size:12px;line-height:1.8em;"> if p.closed {
  41. for {
  42. etorCreate()
  43. return nil,err
  44. // todo maxLifttime处理
  45. return closer,serif;font-size:12px;line-height:1.8em;"> func (p *GenericPool) getorCreate() (io.Closer,serif;font-size:12px;line-height:1.8em;"> select {
  46. case closer := <-p.pool:
  47. default:
  48. p.Lock()
  49. if p.numOpen >= p.maxOpen {
  50. closer := <-p.pool
  51. p.Unlock()
  52. // 新建连接
  53. // 释放单个资源到连接池
  54. func (p *GenericPool) Release(closer io.Closer) error {
  55. return ErrPoolClosed
  56. return nil
  57. // 关闭单个资源
  58. func (p *GenericPool) Close(closer io.Closer) error {
  59. closer.Close()
  60. p.numOpen--
  61. // 关闭连接池,释放所有资源
  62. func (p *GenericPool) Shutdown() error {
  63. close(p.pool)
  64. for closer := range p.pool {
  65. p.closed = true
  66. }
复制代码
结论
基于该连接池,可以管理所有io.Closer对象。比如memcached,redis等等,非常方便!

Golang语言社区论坛网址:www.golang.ltd

相关文章

什么是Go的接口? 接口可以说是一种类型,可以粗略的理解为他...
1、Golang指针 在介绍Golang指针隐式间接引用前,先简单说下...
1、概述 1.1&#160;Protocol buffers定义 Protocol buffe...
判断文件是否存在,需要用到"os"包中的两个函数: os.Stat(...
1、编译环境 OS :Loongnix-Server Linux release 8.3 CPU指...
1、概述 Golang是一种强类型语言,虽然在代码中经常看到i:=1...