GolangNote

Golang笔记

goji + mysql 例子

Permalink

goji + mysql 例子

goji + mysql  例子

完整的例子

// library/database/engine.go

Go: database
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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

Go: resource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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

Go: author
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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

Go: root_repository
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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

Go: author
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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/

Related articles

goji v2 与goji 的对接

goji 是个优秀的框架,作者说以前是弄着玩的,后来较正规的按照go 的设计原则来重构,不过尽量保持原来的接口。...

Write a Comment to "goji + mysql 例子"

Submit Comment Login
Based on Golang + fastHTTP + sdb | go1.16.5 Processed in 23ms