數(shù)據(jù)庫引擎為innodb事務(wù)才有效,myisam引擎是不支持事務(wù)哲鸳。
package main
import (
????_ "github.com/go-sql-driver/mysql"
????"github.com/go-xorm/xorm"
????"os"
????"log"
????"errors"
)
type Account struct {
? ? Id int64 // 主鍵 int64
? ? Name string `xorm:"unique"`? // 唯一索引
? ? Blance float64
? ? Version int `xorm:"version"`? // 樂觀鎖
}
var engine *xorm.Engine
func init () {
????// 根據(jù)名稱注冊驅(qū)動并創(chuàng)建 ORM 引擎
????var err errorengine, err = xorm.NewEngine("mysql", "root:@/go?charset=utf8")
????if err != nil {
????????log.Fatalf("fail to create engine:%v", err)
????}
????if err := engine.Sync(new(Account)); err != nil {
????????log.Fatalf("fail to sync database:%v", err)
????}
????// 記錄SQL語句log
????f, err := os.Create("sql.log")
????if err != nil {
????????log.Fatalf("fail to create log file %v", err)
????}
????// defer f.Close() 打開這行就記錄不到,需要注視掉
????engine.SetLogger(xorm.NewSimpleLogger(f))
????engine.ShowSQL(true)
}
func transfer(id1, id2 int , blance float64) error {
????account_1 := &Account{}
????has1, err := engine.Id(id1).Get(account_1)
????if err != nil {
????return err
????} else if !has1 {
????????return errors.New("account_1 not found")
????}
????account_2 := &Account{}
????has2, err := engine.Id(id2).Get(account_2)
????if err != nil {
????return err
????} else if !has2 {
????????return errors.New("account_2 not found")
????}????
????if account_1.Blance < blance {
????????return errors.New("blance not enough")
????}
????account_1.Blance -= blance
????account_2.Blance += blance
????// 事務(wù)處理
????sess:= engine.NewSession()
????defer sess.Close()
????if err := sess.Begin() ; err != nil {
????????return errors.New("fail to session begin")
????}
????if _, err := sess.Id(id1).Cols("blance").Update(account_1) ; err != nil {
????????sess.Rollback()
????????return errors.New("fail to update 1")
????}
????if _, err := sess.Id(id2).Cols("blance").Update(account_2); err != nil {
????????sess.Rollback()
????????return errors.New("fail to update 2")
????}
????return sess.Commit()
}
func main() {
????// 填充數(shù)據(jù)
????/*
????count, err := engine.Count(new(Account))
????if err != nil {
????????log.Fatal(err.Error())
????}
????for i := count ; i < 10 ; i++ {
????????????demo := Account{
????????????????????Blance :float64(i * 100),
????????????????????Name : fmt.Sprintf("zero_%d", i),
????????????}
????????????if _, err := engine.InsertOne(&demo) ;err != nil {
????????????????????log.Fatal(err.Error())
????????????}
? ? ?}
????*/
????// 轉(zhuǎn)賬
????error := transfer(5, 8, 100)
????if error != nil {
????????log.Fatalf("fail to transfer %v", error)
????}
????fmt.Println("transfer OK")
}
// 執(zhí)行填充數(shù)據(jù)
// 執(zhí)行轉(zhuǎn)賬
go當(dāng)中使用事務(wù)還是很簡單的