mar*_*rkc 10
您的帖子实际上提出了几个问题:
这些实际上是两件不同的事情.连接池只是管理一组连接的一种方法.实现此目的的一种简单方法是使用如下类:
package netpool
import (
"net"
)
const MaxConnections = 3
type Error string
func (e Error) Error() string {
return string(e)
}
var ErrMaxConn = Error("Maximum connections reached")
type Netpool struct {
name string
conns int
free []net.Conn
}
func NewNetpool(name string) *Netpool {
return &Netpool{
name: name,
}
}
func (n *Netpool) Open() (conn net.Conn, err error) {
if n.conns >= MaxConnections && len(n.free) == 0 {
return nil, ErrMaxConn
}
if len(n.free) > 0 {
// return the first free connection in the pool
conn = n.free[0]
n.free = n.free[1:]
} else {
addr, err := net.ResolveTCPAddr("tcp", n.name)
if err != nil {
return nil, err
}
conn, err = net.DialTCP("tcp", nil, addr)
if err != nil {
return nil, err
}
n.conns += 1
}
return conn, err
}
func (n *Netpool) Close(conn net.Conn) error {
n.free = append(n.free, conn)
return nil
}
Run Code Online (Sandbox Code Playgroud)
我在这里创建了一个独立的课程.它通常作为更高级别类的一部分实现,例如MyHTTPHost或MyDatabase.
在这个简单的实现中,不会跟踪通过netpool.Open()返回的连接.可以通过调用Open(),然后关闭netpool.Close()之外的连接来泄漏连接.例如,如果要保留活动和非活动池,可以跟踪它们,这样可以解决此问题.
您可能想要添加到池实现的其他几件事:
一旦建立连接,就可以正常调用Read和Write.要刷新套接字上的所有数据,只需使用ioutil.ReadAll()辅助函数即可.默认情况下,如果没有可用数据,这将无限期阻止.为避免这种情况,请使用以下命令添
conn.SetReadDeadline(time.Now().Add(500 * time.Millisecond))
_, err = ioutil.ReadAll(conn)
neterr, ok := err.(net.Error)
if ok && neterr.Timeout() {
err = nil // timeout isn't an error in this case
}
if err != nil {
// handle the error case.
}
Run Code Online (Sandbox Code Playgroud)
这会从给定的连接,如果任何等待处理,读取所有的数据,如果没有数据待处理后500毫秒将返回与I/O超时错误.
类型断言是必需的,因为ioutil.ReadAll()返回一个Error接口,而不是net.Error接口,我们需要后者能够轻松找出是否由于超时而返回的调用.