七叶笔记 » golang编程 » Golang使用gopg访问MemFireDB数据库

Golang使用gopg访问MemFireDB数据库

本篇介绍如何使用 Golang 访问MemFireDB数据库。

如果大家有个人项目或者公司内部测试项目,推荐大家尝试 MemFire Cloud ,不用自己搭建数据库,在家或者公司随时可以访问。

gopg是Golang中最常用的访问数据库的ORM库,MemFireDB兼容Postgres接口,所以 可以直接把MemFireDB当Postgres使用

在 memfiredb.com 上创建数据库时,可以选择创建 密码 或者 证书 两种认证模式,在公网上部署的数据库,如果存储的是比较 重要的数据,建议使用证书认证模式 ,该模式安全系数要高很多,撞库、彩虹表、暴力破解等传统的密码破解方式对证书认证是无能为力的。如果只是 简单测试,可以使用密码认证方式 ,这种方式配置简单些。

下面是示例代码:

 package main

import (
 "context"
 "flag"
 "fmt"
 "github.com/go-pg/pg/v10"
 "github.com/go-pg/pg/v10/orm"
 "strings"
 "sync"
)

var (
 addr   = flag.String("addr", "192.168.80.161:5433", "memfire address to connect")
 user   = flag.String("user", "test", "memfire user")
 passwd = flag.String("passwd", "test", "memfire password")
 dbname = flag.String("db", "dbname", "memfire database name to connect")
)

func panicIf(err error) {
 if err != nil {
  panic(err)
 }
}

func test_transaction_try_again(db *pg.DB) {
 incrInTx := func(db *pg.DB) error {
  // Transaction is automatically rolled back on error.
  return db.RunInTransaction(db.Context(), func(tx *pg.Tx) error {
   var counter int
   _, err := tx.QueryOne(
    pg.Scan(&counter), `SELECT counter FROM counters FOR UPDATE`)
   if err != nil {
    return err
   }

   counter++

   _, err = tx.Exec(`UPDATE counters SET counter = ?`, counter)
   return err
  })
 }

 var wg sync.WaitGroup
 for i := 0; i < 10; i++ {
  wg.Add(1)
  go func() {
   defer wg.Done()
   for {
    err := incrInTx(db)
    if err != nil {
     if strings.Contains(err.Error(), "40001") ||
      strings.Contains(err.Error(), "Try again") ||
      strings.Contains(err.Error(), "Restart read required") {
      fmt.Println("Try again")
      continue
     }
     panic(err)
    }
    break
   }

  }()
 }
 wg.Wait()
}

type Counter struct {
 Counter int64
}

type User struct {
 Id     int64
 Name   string
 Emails []string
}

// createSchema creates database schema for Counter/ User
func createSchema(db *pg.DB) error {
 models := []interface{}{
  (*Counter)(nil),
  (*User)(nil),
 }

 for _, model := range models {
  err := db.Model(model).CreateTable(&orm.CreateTableOptions{
   Temp:        false,
   IfNotExists: true,
  })
  if err != nil {
   return err
  }
 }
 return nil
}

func main() {
 flag.Parse()

 opt := pg.Options{
  Addr:     *addr,
  User:     *user,
  Password: *passwd,
  Database: *dbname,
  OnConnect: func(ctx context.Context, cn *pg.Conn) error {
   println("new connection created")
   return nil
  },
 }

 db := pg.Connect(&opt)
 defer db.Close()

 err := createSchema(db)
 panicIf(err)

 _, err = db.Exec("delete from counters")
 panicIf(err)

 cnt := &Counter{
  Counter: 1,
 }
 _, err = db.Model(cnt).Insert()
 panicIf(err)

 test_transaction_try_again(db)
}  

相关文章