Design and Implementation of a Generic Connection Pool in Go (Conecta)
This article explains the motivation, design principles, and implementation details of Conecta, a lightweight, configurable Go library that provides a universal connection pool for various services such as databases, TCP/UDP, and custom connections, complete with extensible callbacks and background health checks.
Author LEE, a veteran with 17 years in IT, introduces the need for a lightweight, universal connection pool for various services such as Redis, MySQL, MongoDB, TCP/UDP, etc., and explains why reinventing the wheel is inefficient.
He demonstrates how typical client SDKs (e.g., github.com/go-sql-driver/mysql) provide built‑in pools, but custom scenarios require manual management.
After analyzing existing ad‑hoc implementations (map+lock, channel, third‑party wrappers), he proposes a generic pool built on a channel‑like queue, supporting configurable max connections, idle limits, ping checks, and custom callbacks.
Key design includes a NewPool constructor, Get, Put, GetOrCreate methods, a background goroutine that periodically pings connections, and extensible hooks ( WithNewFunc, WithPingFunc, WithCloseFunc, WithCallback, etc.).
<code style="padding: 16px; color: #333; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">
func execSQL() error {
// 打开数据库
db, err := sql.Open("mysql", "user:password@/dbname")
if err != nil {
return err
}
defer db.Close()
// 执行 SQL 语句
db.Exec("INSERT INTO user (name, age) VALUES (?, ?)", "老李", 18)
return nil
}
</code>The pool can be created with a simple configuration:
<code style="padding: 16px; color: #333; font-family: Operator Mono, Consolas, Monaco, Menso, monospace; font-size: 12px">
pool := NewPool(10, 30, 10*time.Second, func() (interface{}, error) {
// 创建一个 TCP 连接
return net.Dial("tcp", "192.168.0.1:80")
})
defer pool.Close()
conn, err := pool.Get()
if err != nil {
// handle error
}
if _, err := conn.Write([]byte("hello")); err != nil {
conn.Close()
return
}
pool.Put(conn)
</code>A periodic timer checks connection health:
<code style="padding: 16px; color: #333; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">
// 创建一个定时器,每 p.config.scanInterval 毫秒触发一次
ticker := time.NewTicker(time.Millisecond * time.Duration(p.config.scanInterval))
</code>If a connection fails ping checks beyond the maximum retry count, it is closed and the user‑defined OnClose callback is invoked:
<code style="padding: 16px; color: #333; font-family: Operator Mono, Consolas, Monaco, Menlo, monospace; font-size: 12px">
if retryCount >= p.config.maxRetries {
if value != nil {
err := p.config.closeFunc(value)
p.config.callback.OnClose(value, err)
element.SetData(nil)
}
} else {
if ok := p.config.pingFunc(value, retryCount); ok {
element.SetValue(0)
p.config.callback.OnPingSuccess(value)
} else {
element.SetValue(int64(retryCount) + 1)
p.config.callback.OnPingFailure(value)
}
}
</code>The Conecta library (https://github.com/shengyanli1982/conecta) offers a simple API, lifecycle management, and can be integrated with any queue implementation, aiming to reduce duplicated effort across projects.
Conclusion: Conecta provides a reusable, configurable connection‑pool solution for backend services, improving development efficiency and maintainability.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
