[Go] golang缓冲通道实现资源池
go的pool资源池:
1.当有多个并发请求的时候,比如需要查询数据库
2.先创建一个2个容量的数据库连接资源池
3.当一个请求过来的时候,去资源池里请求连接资源,肯定是空的就创建一个连接,执行查询,结束后放入了资源池里
4.当第二个请求过来的时候,也是去资源池请求连接资源,就直接在池中拿过来一个连接进行查询
5.当并发大的时候,资源池里面没有足够连接资源,就会不停创建新资源,放入池里面的时候,也会放不进去,就主动关闭掉这个资源
6.这里的资源池实质上是一个缓冲通道,里面放着连接资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | package main import ( "errors" "io" "log" "math/rand" "sync" "sync/atomic" "time" ) //定义一个结构体,这个实体类型可以作为整体单元被复制,可以作为参数或返回值,或被存储到数组 type Pool struct { //定义成员,互斥锁类型 m sync.Mutex //定义成员,通道类型,通道传递的是io.Closer类型 resources chan io.Closer //定义工厂成员,类型是func()(io.Closer,error) //error是预定义类型,实际上是个interface接口类型 factory func () (io.Closer, error) closed bool } //定义变量,函数返回的是error类型 var ErrPoolClosed = errors.New( "池已经关闭了" ) //定义New方法,创建一个池,返回的是Pool类型的指针 //传入的参数是个函数类型func(io.Closer,error)和池的大小 func New(fn func () (io.Closer, error), size uint) (*Pool, error) { //使用结构体字面值给结构体成员赋值 myPool := Pool{ factory: fn, resources: make( chan io.Closer, size), } //返回两个返回值 return &myPool, nil } //从池中请求获取一个资源,给Pool类型定义的方法 //返回的值是io.Closer类型 func (p *Pool) Acquire() (io.Closer, error) { //基于select的多路复用 //select会等待case中有能够执行的,才会去执行,等待其中一个能执行就执行 //default分支会在所有case没法执行时,默认执行,也叫轮询channel select { case r, _ := <-p.resources: log.Printf( "请求资源:来自通道 %d" , r.(*dbConn).ID) return r, nil //如果缓冲通道中没有了,就会执行这里 default : log.Printf( "请求资源:创建新资源" ) return p.factory() } } //将一个使用后的资源放回池 //传入的参数是io.Closer类型 func (p *Pool) Release(r io.Closer) { //使用mutex互斥锁 p.m.Lock() //解锁 defer p.m.Unlock() //如果池都关闭了 if p.closed { //关掉资源 r.Close() return } //select多路选择 //如果放回通道的时候满了,就关闭这个资源 select { case p.resources <- r: log.Printf( "释放资源:放入通道 %d" , r.(*dbConn).ID) default : log.Printf( "释放资源:关闭资源%d" , r.(*dbConn).ID) r.Close() } } //关闭资源池,关闭通道,将通道中的资源关掉 func (p *Pool) Close() { p.m.Lock() defer p.m.Unlock() p.closed = true //先关闭通道再清空资源 close(p.resources) //清空并关闭资源 for r := range p.resources { r.Close() } } //定义全局常量 const ( maxGoroutines = 20 //使用25个goroutine模拟同时的连接请求 poolSize = 2 //资源池中的大小 ) //定义结构体,模拟要共享的资源 type dbConn struct { //定义成员 ID int32 } //dbConn实现io.Closer接口 func (db *dbConn) Close() error { return nil } var idCounter int32 //定义一个全局的共享的变量,更新时用原子函数锁住 //定义方法,创建dbConn实例 //返回的是io.Closer类型和error类型 func createConn() (io.Closer, error) { //原子函数锁住,更新加1 id := atomic.AddInt32(&idCounter, 1) log.Printf( "创建新资源: %d" , id) return &dbConn{id}, nil } func main() { //计数信号量 var wg sync.WaitGroup //同时并发的数量 wg.Add(maxGoroutines) myPool, _ := New(createConn, poolSize) //开25个goroutine同时查询 for i := 0; i < maxGoroutines; i++ { //模拟请求 time.Sleep(time.Duration(rand.Intn(2)) * time.Second) go func (gid int) { execQuery(gid, myPool) wg.Done() }(i) } //等待上面开的goroutine结束 wg.Wait() myPool.Close() } //定义一个查询方法,参数是当前gorotineId和资源池 func execQuery(goroutineId int, pool *Pool) { //从池里请求资源,第一次肯定是没有的,就会创建一个dbConn实例 conn, _ := pool.Acquire() //将创建的dbConn实例放入了资源池的缓冲通道里 defer pool.Release(conn) //睡眠一下,模拟查询过程 time.Sleep(time.Duration(rand.Intn(10)) * time.Second) log.Printf( "执行查询...协程ID [%d] 资源ID [%d]" , goroutineId, conn.(*dbConn).ID) } |
十年开发经验程序员,离职全心创业中,历时三年开发出的产品《唯一客服系统》
一款基于Golang+Vue开发的在线客服系统,软件著作权编号:2021SR1462600。一套可私有化部署的网站在线客服系统,编译后的二进制文件可直接使用无需搭开发环境,下载zip解压即可,仅依赖MySQL数据库,是一个开箱即用的全渠道在线客服系统,致力于帮助广大开发者/公司快速部署整合私有化客服功能。
开源地址:唯一客服(开源学习版)
官网地址:唯一客服官网
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2016-02-23 [android] 点击事件的四种写法