Golang笔记

goji + mysql 例子

goji + mysql 例子

// library/database/engine.go
package database

import (
    "fmt"
    "time"

    _ "github.com/go-sql-driver/mysql" // load mysql driver for xorm
    "github.com/go-xorm/core"
    "github.com/go-xorm/xorm"
)

var engine *xorm.Engine

func init() {
    loc, err := time.LoadLocation("UTC")
    if err != nil {
        panic(err)
    }
    time.Local = loc
}

// UseEngine reutrns db resource
func UseEngine() *xorm.Engine {
    if engine == nil {
        engine = initEngine()
    }
    return engine
}

func initEngine() *xorm.Engine {
    dbUser := "user"
    dbPass := "pass"
    dbHost := "127.0.0.1"
    dbPort := 3306
    dbName := "blogdb"
    dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", dbUser, dbPass, dbHost, dbPort, dbName)

    e, err := xorm.NewEngine("mysql", dsn)
    if err != nil {
        panic(err)
    }

    // as default mapper, underscore is inserted on every capital case for table or field name.
    // (e.g.) UserID => user_i_d, IPAddress => i_p_address
    // to prevent this rule, use GonicMapper.
    e.SetMapper(core.NewCacheMapper(new(core.GonicMapper)))

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

Go 默认使用连接池,所以把数据链接放在全局变量。同时设置UTC时区,贯穿整个应用。

把数据链接保存在 context 里

// library/net/context/resource/resource_database.go
package resource

import (
    "github.com/go-xorm/xorm"
    "golang.org/x/net/context"

    "github.com/eure/example-blog-golang/library/database"
)

// GetDB returns database engine
func GetDB(c context.Context) *xorm.Engine {
    v, ok := c.Value("database").(*xorm.Engine)
    if !ok {
        return nil
    }
    return v
}

// UseDB returns database engine
func UseDB(c context.Context) *xorm.Engine {
    db := GetDB(c)
    if db == nil {
        db = database.UseEngine()
        c = context.WithValue(c, "database", db)
    }
    return db
}

// UseTx returns database transaction
func UseTx(c context.Context) *xorm.Session {
    tx := c.Value("transaction").(*xorm.Session)
    if tx == nil {
        db := UseDB(c)
        tx := db.NewSession()
        tx.Begin()
        c = context.WithValue(c, "transaction", tx)
    }
    return tx
}

// Commit commits database transaction
func Commit(c context.Context) error {
    tx := c.Value("transaction").(*xorm.Session)
    if tx == nil {
        return nil
    }

    err := tx.Commit()
    if err != nil {
        return err
    }

    c = context.WithValue(c, "transaction", nil)
    tx.Close()
    return nil
}

// Rollback rollbacks database transaction
func Rollback(c context.Context) error {
    tx := c.Value("transaction").(*xorm.Session)
    if tx == nil {
        return nil
    }

    err := tx.Rollback()
    if err != nil {
        return err
    }

    c = context.WithValue(c, "transaction", nil)
    tx.Close()
    return nil
}

// Release releases all resources
func Release(c context.Context) {
    if c == nil {
        return
    }

    tx := c.Value("transaction").(*xorm.Session)
    if tx != nil {
        tx.Close()
    }
}

用户model

// model/author/author_entity.go
package author

import (
    "fmt"
)

// Entity is struct for author
type Entity struct {
    Email string `response:"email" xorm:"pk not null unique"`
    Name  string `response:"name" xorm:"not null unique"`
}

const (
    tableName = "authors"
    pkName    = "email"
)

// TableName define table name for Xorm
func (e Entity) TableName() string {
    return tableName
}

func (e Entity) String() string {
    return fmt.Sprintf("{email: %s, name: %s}", e.Email, e.Name)
}

建立文件

// model/root_repository.go
package model

import (
    "fmt"

    "github.com/go-xorm/xorm"
    "golang.org/x/net/context"

    "github.com/eure/example-blog-golang/library/net/context/resource"
)

// RootRepository is root struct for all repositories
type RootRepository struct {
    Ctx    context.Context
    Engine *xorm.Engine

    PrimaryKey string
    Seed       interface{}
    omitList   []string
}

// NewRootRepositoryWithSeed creates new RootRepository
func NewRootRepositoryWithSeed(ctx context.Context, pk string, seed interface{}) *RootRepository {
    return &RootRepository{
        Ctx:        ctx,
        Engine:     resource.UseDB(ctx),
        PrimaryKey: pk,
        Seed:       seed,
    }
}

// ============================================================
//  helper
// ============================================================

// NewSession return session
func (r *RootRepository) NewSession() *xorm.Session {
    return r.Engine.NewSession()
}

// AddOmit adds column name to omit list
func (r *RootRepository) AddOmit(col string) {
    r.omitList = append(r.omitList, col)
}

// GetLastSQL returns the executed SQL statement
func (r *RootRepository) GetLastSQL(s *xorm.Session) string {
    sql, args := s.LastSQL()
    return fmt.Sprintf("%s -- [args] %v", sql, args)
}

// ============================================================
//  create
// ============================================================

// CreateOne inserts new entity data to database
func (r *RootRepository) CreateOne(e interface{}) error {
    s := r.Engine.NewSession()
    if len(r.omitList) > 0 {
        for _, col := range r.omitList {
            s.Omit(col)
        }
        r.omitList = []string{}
    }

    _, err := s.Insert(e)
    if err != nil {
        return err
    }
    return nil
}

// ============================================================
//  get
// ============================================================

// GetOneByPK fetches a single row by primary key
func (r *RootRepository) GetOneByPK(ent, pk interface{}) (bool, error) {
    s := r.Engine.NewSession()
    s.And(r.PrimaryKey+" = ?", pk)
    return r.GetOneBySession(s, ent)
}

// GetOneBySession fetches a single row using the given session
func (r *RootRepository) GetOneBySession(s *xorm.Session, ent interface{}) (bool, error) {
    has, err := s.Get(ent)
    if err != nil {
        return has, err
    }
    return has, nil
}

Author repository

//  model/author/author_repository.go
package author

import (
    "golang.org/x/net/context"

    "github.com/eure/example-blog-golang/model"
)

// Repository is repo for author
type Repository struct {
    *model.RootRepository
}

// NewRepository creates new Repository
func NewRepository(ctx context.Context) *Repository {
    return &Repository{
        RootRepository: model.NewRootRepositoryWithSeed(ctx, pkName, new(Entity)),
    }
}


// GetByEmail fetches a single author by email
func (r *Repository) GetByEmail(email string) *Entity {
    ent := new(Entity)
    has, err := r.GetOneByPK(ent, email)
    switch {
    case err != nil:
        // TODO: logging
        return nil
    case !has:
        return nil
    }
    return ent
}

摘自 https://developers.eure.jp/go-language/advent-calendar-20/ 2

本文网址: https://golangnote.com/topic/117.html (转载注明出处)
关于GolangNote:记录在工作中使用golang 遇到、面临的相关问题及解决方法。如果你在这里获得一些知识或信息,解决你的编程问题,请考虑捐赠给不幸的人或者你喜欢的慈善机构,除捐赠外,种植树木、志愿服务或减少排碳的行为也很有益处。如果你有任何问题可以在下面 留言
Be the first to comment!
Captcha image
Relative Articles