Golang1.7.4标准库sql使用

package main

import (
    "database/sql"
    "errors"
    "fmt"
    "net"
    "sync/atomic"
    "time"

    "github.com/go-sql-driver/mysql"
)

func main() {}

//新建mysql连接,connstr为mysql连接串"root:123456@tcp(172.18.80.211:3306)/workstacks?charset=utf8"
//maxopen为最大连接数
func NewMysql(connstr string, maxopen int) (*_mysql, error) {
    m := &_mysql{connstr: connstr, maxopen: maxopen}
    err := m.dial()
    return m, err
}

var UnavailableError = errors.New("Status Unavailable")

type _mysql struct {
    connstr string
    maxopen int
    db      *sql.DB
    status  uint32
}

//初始化连接串
func (s *_mysql) init() error {
    db, err := sql.Open("mysql", s.connstr)
    if err != nil {
        return err
    }
    if s.maxopen <= 0 {
        db.SetMaxOpenConns(20)
    } else {
        db.SetMaxOpenConns(s.maxopen)
    }
    s.db = db
    return nil
}

//连接数据库,当网络不可达的时候会循环连接,知道连接成功,每次连接等待时间会递增,最大等待时间为120s
func (s *_mysql) dial() error {
    if s.db == nil {
        err := s.init()
        if err != nil {
            return err
        }
    }
    var rtime time.Duration = 10
redial:
    err := s.db.Ping()
    if err != nil {
        if _, ok := err.(*mysql.MySQLError); ok {
            return err
        }
        if isNetError(err) {
            <-time.After(rtime * time.Second)
            if rtime < 120 {
                rtime += 10
            }
            fmt.Println(err)
            goto redial
        }
        return err
    }
    s.SetStatus(1)
    return nil
}

//重置数据库连接信息
func (s *_mysql) Reset(connstr string, maxopen int) error {
    db, err := sql.Open("mysql", connstr)
    if err != nil {
        return err
    }
    if maxopen <= 0 {
        db.SetMaxOpenConns(20)
    } else {
        db.SetMaxOpenConns(maxopen)
    }

    err = db.Ping()
    if err != nil {
        return err
    }

    s.connstr = connstr
    s.maxopen = maxopen
    tmpdb := s.db
    s.db = db
    tmpdb.Close()
    return nil
}

//执行SQL语句,insert,update,delete等
func (s *_mysql) Exec(query string, args ...interface{}) (sql.Result, error) {
    if s.Status() {
        result, err := s.db.Exec(query, args...)
        if err != nil {
            if isNetError(err) {
                s.SetStatus(0)
                if err = s.dial(); err == nil {
                    return s.Exec(query, args...)
                }
                return nil, err
            }
        }
        return result, err
    }
    return nil, UnavailableError
}

//执行SQL查询
func (s *_mysql) Query(query string, args ...interface{}) (*sql.Rows, error) {
    if s.Status() {
        rows, err := s.db.Query(query, args...)
        if err != nil {
            if isNetError(err) {
                s.SetStatus(0)
                if err = s.dial(); err == nil {
                    return s.Query(query, args...)
                }
                return nil, err
            }
        }
        return rows, err
    }
    return nil, UnavailableError
}

//查看当前状态是否可用,返回true表示可用
func (s *_mysql) Status() bool {
    return atomic.LoadUint32(&s.status) != 0
}

//设置状态,0表示状态不可用,1表示状态可用
func (s *_mysql) SetStatus(status uint32) {
    atomic.StoreUint32(&s.status, status)
}

//关闭数据库连接
func (s *_mysql) Close() {
    if s.db != nil {
        s.db.Close()
    }
}
func isNetError(err error) bool {
    _, ok := err.(*net.OpError)
    return ok
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值