package pool
import (
"errors"
"io"
"sync"
"time"
) var (
ErrInvalidConfig = errors.New("invalid pool config")
ErrPoolClosed = errors.New("pool closed")
) type factory func() (io.Closer, error) type Pool interface {
Acquire() (io.Closer, error) // 获取资源
Release(io.Closer) error // 释放资源
Close(io.Closer) error // 关闭资源
Shutdown() error // 关闭池
} type GenericPool struct {
sync.Mutex
pool chan io.Closer
maxOpen int // 池中最大资源数
numOpen int // 当前池中资源数
minOpen int // 池中最少资源数
closed bool // 池是否已关闭
maxLifetime time.Duration
factory factory // 创建连接的方法
} func NewGenericPool(minOpen, maxOpen int, maxLifetime time.Duration, factory factory) (*GenericPool, error) {
if maxOpen <= 0 || minOpen > maxOpen {
return nil, ErrInvalidConfig
}
p := &GenericPool{
maxOpen: maxOpen,
minOpen: minOpen,
maxLifetime: maxLifetime,
factory: factory,
pool: make(chan io.Closer, maxOpen),
} for i := 0; i < minOpen; i++ {
closer, err := factory()
if err != nil {
continue
}
p.numOpen++
p.pool <- closer
}
return p, nil
} func (p *GenericPool) Acquire() (io.Closer, error) {
if p.closed {
return nil, ErrPoolClosed
}
for {
closer, err := p.getOrCreate()
if err != nil {
return nil, err
}
// todo maxLifttime处理
return closer, nil
}
} func (p *GenericPool) getOrCreate() (io.Closer, error) {
select {
case closer := <-p.pool:
return closer, nil
default:
}
p.Lock()
if p.numOpen >= p.maxOpen {
closer := <-p.pool
p.Unlock()
return closer, nil
}
// 新建连接
closer, err := p.factory()
if err != nil {
p.Unlock()
return nil, err
}
p.numOpen++
p.Unlock()
return closer, nil
} // 释放单个资源到连接池
func (p *GenericPool) Release(closer io.Closer) error {
if p.closed {
return ErrPoolClosed
}
p.Lock()
p.pool <- closer
p.Unlock()
return nil
} // 关闭单个资源
func (p *GenericPool) Close(closer io.Closer) error {
p.Lock()
closer.Close()
p.numOpen--
p.Unlock()
return nil
} // 关闭连接池,释放所有资源
func (p *GenericPool) Shutdown() error {
if p.closed {
return ErrPoolClosed
}
p.Lock()
close(p.pool)
for closer := range p.pool {
closer.Close()
p.numOpen--
}
p.closed = true
p.Unlock()
return nil
}

  转:https://www.jb51.net/article/134302.htm

golang 基于channel封装资源池(可用于封装redis、mq连接池)的更多相关文章

  1. redis mysql 连接池 之 golang 实现

    1 mysql 连接池代码 package lib import ( "database/sql" "fmt" "strconv" &quo ...

  2. Go/Python/Erlang编程语言对比分析及示例 基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池) 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!

    Go/Python/Erlang编程语言对比分析及示例   本文主要是介绍Go,从语言对比分析的角度切入.之所以选择与Python.Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性, ...

  3. 分享基于.NET动态编译&Newtonsoft.Json封装实现JSON转换器(JsonConverter)原理及JSON操作技巧

    看文章标题就知道,本文的主题就是关于JSON,JSON转换器(JsonConverter)具有将C#定义的类源代码直接转换成对应的JSON字符串,以及将JSON字符串转换成对应的C#定义的类源代码,而 ...

  4. [分享] 史上最简单的封装教程,五分钟学会封装系统(以封装Windows 7为例)

    [分享] 史上最简单的封装教程,五分钟学会封装系统(以封装Windows 7为例) 踏雁寻花 发表于 2015-8-23 23:31:28 https://www.itsk.com/thread-35 ...

  5. Redisclient连接方式Hiredis简单封装使用,连接池、屏蔽连接细节

    工作须要对Hiredis进行了简单封装,实现功能: 1.API进行统一,对外仅仅提供一个接口. 2.屏蔽上层应用对连接的细节处理: 3.底层採用队列的方式保持连接池,保存连接会话. 4.重连时採用时间 ...

  6. golang的channel实现

    golang的channel实现位于src/runtime/chan.go文件.golang中的channel对应的结构是: // Invariants: // At least one of c.s ...

  7. Dapper的封装、二次封装、官方扩展包封装,以及ADO.NET原生封装

    前几天偶然看到了dapper,由于以前没有用过,只用过ef core,稍微看了一下,然后写了一些简单的可复用的封装. Dapper的用法比较接近ADO.NET所以性能也是比较快.所以我们先来看看使用A ...

  8. SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装

    SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装 >>>>>>>& ...

  9. Spring NamedParameterJdbcTemplate命名参数查询条件封装, NamedParameterJdbcTemplate查询封装

    Spring NamedParameterJdbcTemplate命名参数查询条件封装, NamedParameterJdbcTemplate查询封装 >>>>>> ...

随机推荐

  1. Tortoise Git 安装 及报错处理

    TortoiseGit安装详解: https://www.cnblogs.com/xinlj/p/5978730.html Tortoise Git 错误处理 disconnected no supp ...

  2. mssql提权

    MSSQL的提权:下面是三种方法一种利用xp_cmshell组件,还有一种sp_OACreate组件,COM组件 xp_cmshell组件的开启: 1.sql2005版本以后默认为关闭状态,需要开启命 ...

  3. Tips on Blind Source Separation

    盲源分离是指在不知道源信号和信道传输参数的情况下,根据输入信号的统计特性,仅由观测信号恢复出源信号各个独立成分的过程.盲源分离研究的信号模型主要有三种:线性混合模型.卷积混合模型和非线性混合模型. 1 ...

  4. SpringBoot第三节(thymeleaf的配置与SpringBoot注解大全)

    Springboot默认是不支持JSP的,默认使用thymeleaf模板引擎.所以这里介绍一下Springboot使用Thymeleaf的实例以及遇到的问题. 1.配置与使用 1.1:在applica ...

  5. gdb命令行

    1.当程序出现core dump时,使用下面的命令调试:       gdb 程序名 core.1234  或       gdb core.1234       gdb -c core.1234 程 ...

  6. let

    let a=2+2 #+ - * / % ** 都支持 支持类C的计算方式 let i++ let i-- let i+=10 let i-=10 let i*=10 let i/=10 let i% ...

  7. 开源项目 08 IOC Autofac

    using Autofac; using System; using System.Collections.Generic; using System.Linq; using System.Text; ...

  8. libreoj #10153 树形dp

    $des$ 有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点.这棵树共 NNN 个节点,标号 1 至 N,树根编号一定为 1. 我们用一根树枝两端连接的节点编号描述一根树枝的位 ...

  9. 奶牛抗议 DP 树状数组

    奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i] ...

  10. element ui 怎么去修改el-date-picker的时间

    <el-date-picker v-model="formSearch.timeRange" type="daterange" placeholder=& ...