func (p *ConnPool) Prepare(name, sql string) (*PreparedStatement, error) {
	return p.PrepareEx(name, sql, nil)
}
Prepare creates a prepared statement on a connection in the pool to test the
statement is valid. If it succeeds all connections accessed through the pool
will have the statement available.

Prepare creates a prepared statement with name and sql. sql can contain
placeholders for bound parameters. These placeholders are referenced
positional as $1, $2, etc.

Prepare is idempotent; i.e. it is safe to call Prepare multiple times with
the same name and sql arguments. This allows a code path to Prepare and
Query/Exec/PrepareEx without concern for if the statement has already been prepared.
package pgx
import (
	"errors"
	"sync"
	"time"
)
type ConnPoolConfig struct {
	ConnConfig
	MaxConnections int                
	AfterConnect   func(*Conn) error  
	AcquireTimeout time.Duration      
}
type ConnPool struct {
	allConnections       []*Conn
	availableConnections []*Conn
	cond                 *sync.Cond
	config               ConnConfig  
	maxConnections       int
	resetCount           int
	afterConnect         func(*Conn) error
	logger               Logger
	logLevel             int
	closed               bool
	preparedStatements   map[string]*PreparedStatement
	acquireTimeout       time.Duration
	pgTypes              map[Oid]PgType
	pgsql_af_inet        *byte
	pgsql_af_inet6       *byte
}
type ConnPoolStat struct {
	MaxConnections       int  
	CurrentConnections   int  
	AvailableConnections int  
}
func NewConnPool(config ConnPoolConfig) (p *ConnPool, err error) {
	p = new(ConnPool)
	p.config = config.ConnConfig
	p.maxConnections = config.MaxConnections
	if p.maxConnections == 0 {
		p.maxConnections = 5
	}
	if p.maxConnections < 1 {
		return nil, errors.New("MaxConnections must be at least 1")
	}
	p.acquireTimeout = config.AcquireTimeout
	if p.acquireTimeout < 0 {
		return nil, errors.New("AcquireTimeout must be equal to or greater than 0")
	}
	p.afterConnect = config.AfterConnect
	if config.LogLevel != 0 {
		p.logLevel = config.LogLevel
	} else {
		p.logLevel = LogLevelDebug
	}
	p.logger = config.Logger
	if p.logger == nil {
		p.logLevel = LogLevelNone
	}
	p.allConnections = make([]*Conn, 0, p.maxConnections)
	p.availableConnections = make([]*Conn, 0, p.maxConnections)
	p.preparedStatements = make(map[string]*PreparedStatement)
	p.cond = sync.NewCond(new(sync.Mutex))
	var c *Conn
	c, err = p.createConnection()
	if err != nil {
		return
	}
	p.allConnections = append(p.allConnections, c)
	p.availableConnections = append(p.availableConnections, c)
	return
}
func (p *ConnPool) Acquire() (*Conn, error) {
	p.cond.L.Lock()
	c, err := p.acquire(nil)
	p.cond.L.Unlock()
	return c, err
}
func (p *ConnPool) acquire(deadline *time.Time) (*Conn, error) {
	if p.closed {
		return nil, errors.New("cannot acquire from closed pool")
	}
	if len(p.availableConnections) > 0 {
		c := p.availableConnections[len(p.availableConnections)-1]
		c.poolResetCount = p.resetCount
		p.availableConnections = p.availableConnections[:len(p.availableConnections)-1]
		return c, nil
	}
	if len(p.allConnections) < p.maxConnections {
		c, err := p.createConnection()
		if err != nil {
			return nil, err
		}
		c.poolResetCount = p.resetCount
		p.allConnections = append(p.allConnections, c)
		return c, nil
	}
	if p.logLevel >= LogLevelWarn {
		p.logger.Warn("All connections in pool are busy - waiting...")
	}
	if deadline == nil && p.acquireTimeout > 0 {
		tmp := time.Now().Add(p.acquireTimeout)
		deadline = &tmp
	}
	if deadline != nil {
		timer := time.AfterFunc(deadline.Sub(time.Now()), func() {
			p.cond.Signal()
		})
		defer timer.Stop()
	}
	for len(p.availableConnections) == 0 && len(p.allConnections) == p.maxConnections {
		if deadline != nil && time.Now().After(*deadline) {
			return nil, errors.New("Timeout: All connections in pool are busy")
		}
		p.cond.Wait()
	}
	return p.acquire(deadline)
}
func (p *ConnPool) Release(conn *Conn) {
	if conn.TxStatus != 'I' {
		conn.Exec("rollback")
	}
	if len(conn.channels) > 0 {
		if err := conn.Unlisten("*"); err != nil {
			conn.die(err)
		}
		conn.channels = make(map[string]struct{})
	}
	conn.notifications = nil
	p.cond.L.Lock()
	if conn.poolResetCount != p.resetCount {
		conn.Close()
		p.cond.L.Unlock()
		p.cond.Signal()
		return
	}
	if conn.IsAlive() {
		p.availableConnections = append(p.availableConnections, conn)
	} else {
		ac := p.allConnections
		for i, c := range ac {
			if conn == c {
				ac[i] = ac[len(ac)-1]
				p.allConnections = ac[0 : len(ac)-1]
				break
			}
		}
	}
	p.cond.L.Unlock()
	p.cond.Signal()
}
func (p *ConnPool) Close() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()
	p.closed = true
	if len(p.availableConnections) != len(p.allConnections) {
		for len(p.availableConnections) != len(p.allConnections) {
			p.cond.Wait()
		}
	}
	for _, c := range p.allConnections {
		_ = c.Close()
	}
}
func (p *ConnPool) Reset() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()
	p.resetCount++
	p.allConnections = make([]*Conn, 0, p.maxConnections)
	p.availableConnections = make([]*Conn, 0, p.maxConnections)
}
func (p *ConnPool) invalidateAcquired() {
	p.resetCount++
	for _, c := range p.availableConnections {
		c.poolResetCount = p.resetCount
	}
	p.allConnections = p.allConnections[:len(p.availableConnections)]
	copy(p.allConnections, p.availableConnections)
}
func (p *ConnPool) Stat() (s ConnPoolStat) {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()
	s.MaxConnections = p.maxConnections
	s.CurrentConnections = len(p.allConnections)
	s.AvailableConnections = len(p.availableConnections)
	return
}
func (p *ConnPool) createConnection() (*Conn, error) {
	c, err := connect(p.config, p.pgTypes, p.pgsql_af_inet, p.pgsql_af_inet6)
	if err != nil {
		return nil, err
	}
	p.pgTypes = c.PgTypes
	p.pgsql_af_inet = c.pgsql_af_inet
	p.pgsql_af_inet6 = c.pgsql_af_inet6
	if p.afterConnect != nil {
		err = p.afterConnect(c)
		if err != nil {
			c.die(err)
			return nil, err
		}
	}
	for _, ps := range p.preparedStatements {
		if _, err := c.Prepare(ps.Name, ps.SQL); err != nil {
			c.die(err)
			return nil, err
		}
	}
	return c, nil
}
func (p *ConnPool) Exec(sql string, arguments ...interface{}) (commandTag CommandTag, err error) {
	var c *Conn
	if c, err = p.Acquire(); err != nil {
		return
	}
	defer p.Release(c)
	return c.Exec(sql, arguments...)
}
func (p *ConnPool) Query(sql string, args ...interface{}) (*Rows, error) {
	c, err := p.Acquire()
	if err != nil {
		return &Rows{closed: true, err: err}, err
	}
	rows, err := c.Query(sql, args...)
	if err != nil {
		p.Release(c)
		return rows, err
	}
	rows.AfterClose(p.rowsAfterClose)
	return rows, nil
}
func (p *ConnPool) QueryRow(sql string, args ...interface{}) *Row {
	rows, _ := p.Query(sql, args...)
	return (*Row)(rows)
}
func (p *ConnPool) Begin() (*Tx, error) {
	return p.BeginIso("")
}