go---数据库

采用 Ioc 模式

mysql.go

package common

import (
    "sync"
    "time"

    _ "code.byted.org/gopkg/mysql-driver"  // init mysql-driver
    raven "github.com/getsentry/raven-go"
    "code.byted.org/gopkg/gorm"

    "config"
)

var (
    readDB    *gorm.DB
    writeDB   *gorm.DB
    infosysDB *gorm.DB
    dbOnce    sync.Once
)

const (
    maxOpenConns       = 90
    maxIdleConns       = 90
    maxConnMaxLifetime = 200 * time.Second
)

func getDB(mySQLAddr string) *gorm.DB {
    db, err := gorm.Open("mysql2", mySQLAddr)
    if err != nil {
        raven.CaptureError(err, nil)
        panic(err)
    }
    db.SingularTable(true)
    db.DB().SetMaxOpenConns(maxOpenConns)
    db.DB().SetMaxIdleConns(maxIdleConns)
    db.DB().SetConnMaxLifetime(maxConnMaxLifetime)
    return db
}

func initDBs() {
    conf := config.GetConfig()
    readDB = getDB(conf.MySQLReadAddr)
    writeDB = getDB(conf.MySQLWriteAddr)
    infosysDB = getDB(conf.RedisAddr)
}

// GetReadDB .
func GetReadDB() *gorm.DB {
    dbOnce.Do(initDBs)
    return readDB
}

// GetWriteDB .
func GetWriteDB() *gorm.DB {
    dbOnce.Do(initDBs)
    return writeDB
}

// GetInfosysDB .
func GetInfosysDB() *gorm.DB {
    dbOnce.Do(initDBs)
    return infosysDB
}

redis.go

package common

import (
    "sync"
    "time"

    "git.byted.org/eerd/danger/core/config"
    "github.com/getsentry/raven-go"
    "github.com/go-redis/redis"
)

var (
    redisClient     *redis.Client
    redisClientOnce sync.Once
)

func initRedisClient() {
    conf := config.GetConfig()
    redisClient = redis.NewClient(&redis.Options{
        Addr: conf.RedisAddr,
    })

    err := redisClient.Set("PingTest", true, 1*time.Second).Err()
    if err != nil {
        raven.CaptureError(err, nil)
        panic(err)
    }
}

// GetRedisClient .
func GetRedisClient() *redis.Client {
    redisClientOnce.Do(initRedisClient)
    return redisClient
}

以上文件中需要用到数据库地址,位于 config.go 中

package config

import (
    "encoding/base64"
    "fmt"
    "os"
    "strings"
    "sync"

    "github.com/getsentry/raven-go"
    "git.byted.org/gopkg/configor"
    "git.byted.org/gopkg/kmsconf"
    "github.com/sirupsen/logrus"

    // 以下略去自己写的包
)

type Config struct {
    MySQLReadAddr    string `yaml:"mysql_read_addr"`
    MySQLWriteAddr   string `yaml:"mysql_write_addr"`
    MySQLInfosysAddr string `yaml:"mysql_infosys_addr"`
    RedisAddr        string `yaml:"redis_addr"`

    SessionKey       []byte `yaml:"-"`
    SessionKeyBase64 string `yaml:"session_key"`
}

var (
    config *Config
    once   sync.Once
)

func IsOnline() bool {
    return os.Getenv("ENV") == "online"
}

func getSessionKey() string {
    // recommended: need kms psm to discovery kms service
    config, err := kmsconf.NewConfig("abcdefg", "higjklm-1234")
    if err != nil {
        logrus.Errorf("Cache init: %s", err)
    }

    // get key directly
    v, err := config.Get("asdffd.skey")
    if err != nil {
        logrus.Errorf("Cache init: %s", err)
    }

    return v.(string)
}

func initConfig() {
    conf := &Config{}
    env := os.Getenv("ENV")

    // 通过 yml 文件为结构体赋值
    err := configor.New(&configor.Config{Environment: env}).Load(
        conf, "./config.yml",
    )

    if IsOnline() {
        if strings.HasPrefix(conf.RedisAddr, "consul:") {
            redisHost, err := consul.RandomChoise(strings.TrimPrefix(conf.RedisAddr, "consul:"))
            if err != nil {
                raven.CaptureError(err, nil)
                panic(err)
            }
            conf.RedisAddr = fmt.Sprintf("%s:%d", redisHost.Host, redisHost.Port)

            // 从 KMS 中取出 SessionKey
            conf.SessionKeyBase64 = getSessionKey()
        }
    }

    sessionKey, err := base64.StdEncoding.DecodeString(conf.SessionKeyBase64)
    if err != nil {
        raven.CaptureError(err, nil)
        panic(err)
    }
    conf.SessionKey = sessionKey

    config = conf
}

func GetConfig() *Config {
    once.Do(initConfig)
    return config
}

以上文件需要 config.yml 提供地址

mysql_read_addr: "root:dev@(mysql:3306)/abcdef?charset=utf8mb4&parseTime=True&timeout=90s"
mysql_write_addr: "root:dev@(mysql:3306)/abcdef?charset=utf8mb4&parseTime=True&timeout=90s"
mysql_infosys_addr: "root:dev@(mysql:3306)/abcdef?charset=utf8mb4&parseTime=True&timeout=90s"
redis_addr: "127.0.0.1"
session_key: "12345678"

接下来可以进行查询了

package reports

import (
    "time"

    // 以下略去自己写的包
)

func GetReportsFromDatabase(start, end time.Time) (*[]*models.Report, error) {
    dbReports := &[]*models.Report{}  
    err := GetReadDB().Select(
        "`id`, `time`, `type`, MIN(`ltime`) AS `mintime`, MAX(`ltime`) AS `maxtime`",
    ).Group(
        "`id`, `time`, `type`",
    ).Where(
        "`time` >= ? AND `time` <= ?", start, end,
    ).Order(
        "`id`, `time`, `type`",
    ).Find(dbReports).Error   // 直接将查询结果赋给结构体数组
    return dbReports, err
}

猜你喜欢

转载自blog.csdn.net/u012319493/article/details/81198515