• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Go语言操作数据库及其常规操作的示例代码

    Go操作MySQL

    安装: go get -u github.com/go-sql-driver/mysql

    GO语言的操作数据库的驱动原生支持连接池, 并且是并发安全的 标准库没有具体的实现 只是列出了一些需要的第三方库实现的具体内容

    //第一次连接MySQL成功
    package main
    
    import (
     "database/sql"
     _ "github.com/go-sql-driver/mysql"   // _想当于init()初始化
     "log"
    )
    
    func main() {
     // root 用户名 1qa2ws3ed是密码  后边的书ip:port  gouse 库名
     dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse"
     db, err := sql.Open("mysql", dsn)
     if err != nil {
      panic(err)
     }
     // ping是尝试连接MySQL数据库
     
     if err = db.Ping(); err != nil{
      panic(err)
     }
     log.Fatalln("Mysql数据库连接成功")
    
    }

    Go调用MySQL封装成函数

    package main
    
    import (
     "database/sql"
     "encoding/json"
     "fmt"
     _ "github.com/go-sql-driver/mysql"
    )
    
    var db *sql.DB
    
    func InitDB() (err error) {
     dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse"
    
     db, err = sql.Open("mysql", dsn)
     CheckErr(err)
    
     err = db.Ping()
     CheckErr(err)
     fmt.Println("数据库连接成功...")
     // 设置数据库连接池最大连接数
     db.SetConnMaxLifetime(10)
    
     //设置最大闲置连接数
     db.SetMaxIdleConns(5)
    
     return
    }
    
    type data struct {
     Username string `json:"username"`
     Password string `json:"password"`
    }
    
    
    func main()  {
     err := InitDB()
     CheckErr(err)
    
     query, err := db.Query("select username, password from test")
     CheckErr(err)
    
     for query.Next(){
      line := data{}
      // 查询数据的时候必须要调用scan方法如果 没有 使用scan  连接通道一直保持连接 无法释放连接  
      _ = query.Scan(line.Username, line.Password)
      fmt.Println(line)
      dataDic := map[string]string{
       "username": line.Username,
       "password": line.Password,
      }
      marshal, _ := json.Marshal(dataDic)
      fmt.Println(string(marshal))
     }
    }
    
    func CheckErr(err error) {
     if err != nil {
      fmt.Println(err)
      panic(err)
     }
    }

    GO—MySQL的增删改查

    package main
    
    import (
     "database/sql"
     "encoding/json"
     "fmt"
     "time"
    
     _ "github.com/go-sql-driver/mysql"
    )
    
    var db *sql.DB
    
    // InitDB 数据库连接初始化
    func InitDB() (err error) {
     dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse"
    
     db, err = sql.Open("mysql", dsn)
     CheckErr(err)
    
     err = db.Ping()
     CheckErr(err)
     fmt.Println("数据库连接成功...")
     // 设置数据库连接池最大连接数
     db.SetConnMaxLifetime(10)
    
     //设置最大闲置连接数
     db.SetMaxIdleConns(5)
    
     return
    
    }
    
    type data struct {
     Username string `json:"username"`
     Password string `json:"password"`
    }
    
    // SelectQuery 查询函数
    func SelectQuery() {
     sqlStr := "select username, password from test where id > ?"
     query, err := db.Query(sqlStr, 1)
     CheckErr(err)
     defer query.Close()
    
     fmt.Printf("现在是北京时间 %s , 你今天进步了吗?\n", time.Now().Format("2006-01-02 15:04:05"))
    
     for query.Next() {
      line := data{}
      // 查询数据的时候必须要调用scan方法如果 没有 使用scan  连接通道一直保持连接 无法释放连接
      _ = query.Scan(line.Username, line.Password)
      //fmt.Println(line)
      dataDic := map[string]string{
       "username": line.Username,
       "password": line.Password,
      }
      marshal, _ := json.Marshal(dataDic)
      fmt.Printf("查询到的数据为 %s\n", string(marshal))
     }
    }
    
    // InsertQuery 插入数据
    func InsertQuery() {
     // sql 语句
     sqlStr := `insert into test (username,password) values ("kuQi", "123qwe")`
     result, err := db.Exec(sqlStr)
     CheckErr(err)
     id, err := result.LastInsertId()
     CheckErr(err)
     fmt.Printf("插入成功数据的id为 %v", id)
    }
    
    // UpdateQuery 更新数据函数
    func UpdateQuery(dataField string, user string) {
     sqlStr := `update test set password=? where username=?`
     result, err := db.Exec(sqlStr, dataField, user)
     CheckErr(err)
     rowsAffected, err := result.RowsAffected()
     CheckErr(err)
     fmt.Printf("被更新字段的id为%d\n", rowsAffected)
    
    }
    
    // DeleteQuery 删除
    func DeleteQuery(id int) {
     sqlStr := `delete from test where id=?`
     result, err := db.Exec(sqlStr, id)
     CheckErr(err)
     rowsAffected, err := result.RowsAffected()
     CheckErr(err)
     if rowsAffected == 0 {
      fmt.Printf("没有匹配到要删除的id=%d数据", id)
      return
     }
     fmt.Printf("删除数据库的id为%d", id)
    
    }
    
    //CheckErr 异常捕获函数
    func CheckErr(err error) {
     if err != nil {
      fmt.Println(err)
      panic(err)
     }
    }
    
    // main 主函数 所有函数的入口
    func main() {
     err := InitDB()
     CheckErr(err)
    
     //InsertQuery()
     UpdateQuery("hahaGolang123", "kuQi")
     SelectQuery()
     DeleteQuery(5)
    }
    
    

    MySQL的预处理

    什么是预处理?
    普通SQL语句执行过程:
     1.客户端对SQL语句进行占位符的替换得到了完整的SQL语句
     2.客户端发送完整SQL语句到MySQL服务端
     3.MySQL服务端执行完整的SQL语句并将结果返回终端

    预处理的执行过程
     1.先把SQL语句拆分成两部分,SQL语句部分和参数部分
     2.先把SQL语句部分发送给MySQL服务端进行SQL预处理
     3.然后参数部分发送给MySQL服务端,MySQL对SQL语句进行拼接
     4.MySQL服务端执行完整的SQL语句返回结果

    为什么要进行预处理?
      1.为了优化MySQL服务器重复执行SQL的方法。可以执行服务器的性能,提前让服务器编译,一次编译多次执行,节省后续重复编译的成本
      2.并且避免SQL注入

    Go实现MySQL预处理

    // prepare方法现将SQL发送到MySQL服务端, 返回一个准备好的状态用于之后的查询和命令。返回值可以同时执行多个查询和命令  ; 命令也就是SQL语句
    // PrepareInsert 预处理执行插入语句
    func PrepareInsert() {
    
     defer wg.Done()
     sqlStr := `insert into test (username, password) values (?, ?)`
     // - 预处理 stmt 就是编译好的sql语句 之后直接传递参数即可
     stmt, err := db.Prepare(sqlStr)
     var u1 = uuid.Must(uuid.NewV4())
     CheckErr(err)
     defer stmt.Close()
     i := rand.Int()
    
     username := fmt.Sprintf("yonghuming%d", i)
     result, err := stmt.Exec(username, u1.String()[:10])
     CheckErr(err)
     rowsAffected, err := result.LastInsertId()
     CheckErr(err)
     fmt.Printf("成功插入id=%d条数据\n", rowsAffected)
    }
    
    

    Go语言实现MySQL实现事务操作

    // go语言中使用一下三个方法实现MySQL中的事务操作, 开始事务
    func (db *DB) Begin()(*Tx, error)
    
    // 提交事务  相当与Python中的conn.commit()
    func (tx *Tx) Commit() error   
    
    // 回滚事务
    func (tx *Tx) Rollback() error
    
    package main
    
    import (
     "database/sql"
     "fmt"
    
     _ "github.com/go-sql-driver/mysql"
    )
    
    var db *sql.DB
    
    type data struct {
     Username string `json:"username"`
     Password string `json:"password"`
    }
    
    // InitDB 数据库连接初始化
    func InitDB() (err error) {
     dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse"
    
     db, err = sql.Open("mysql", dsn)
     CheckErr(err)
    
     err = db.Ping()
     CheckErr(err)
     fmt.Println("数据库连接成功...")
     // 设置数据库连接池最大连接数
     db.SetMaxOpenConns(100)
    
     //设置最大闲置连接数
     db.SetMaxIdleConns(5)
    
     return
    
    }
    
    //CheckErr 异常捕获函数
    func CheckErr(err error) {
     if err != nil {
      fmt.Println(err)
      panic(err)
     }
    }
    
    // TranSaCtIon MySQL的事务操作
    func TranSaCtIon() {
     // 开启事务
     tx, err := db.Begin()
     CheckErr(err)
    
     // 执行多个SQL操作
     sqlStr := `update test set id=id+100000 where password=?`
     result, err := tx.Exec(sqlStr, "07f70f7e-4")
     CheckErr(err)
     id, err := result.LastInsertId()
     if err != nil {
      // 语句回滚
      err := tx.Rollback()
      fmt.Println("事务回滚")
      CheckErr(err)
    
     }
     fmt.Printf("修改后的id为%d\n", id)
    
    }
    
    func main() {
     err := InitDB()
     CheckErr(err)
     TranSaCtIon()
    }
    
    

    sqlx使用

    第三方库sqlx能够简化操作,提高开发效率

    安装go get github.com/jmoiron/sqlx

    package main
    
    import (
     "fmt"
    
     _ "github.com/go-sql-driver/mysql"
     "github.com/jmoiron/sqlx"
    )
    
    var db *sqlx.DB
    
    // InitDB 数据库初始化
    func InitDB() (err error) {
     dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse"
     db, err = sqlx.Connect("mysql", dsn)
     CheckErr(err)
     db.SetMaxOpenConns(50)
     db.SetMaxIdleConns(10)
     fmt.Println("goUse 数据库连接成功")
     return
    }
    
    //CheckErr 异常捕获函数
    func CheckErr(err error) {
     if err != nil {
      fmt.Println(err)
      panic(err)
     }
    }
    
    func main() {
     err := InitDB()
     CheckErr(err)
    }

    sqlx相较于原生的sql库好处在于 查询的时候sql原生的需要next scan 回调获取结果

    sqlx 查询只需要定义一个存储的变量 然后自动就会将查询的出来的值放入变量中

    package main
    
    import (
     "encoding/json"
     "fmt"
    
     _ "github.com/go-sql-driver/mysql"
     "github.com/jmoiron/sqlx"
    )
    
    var db *sqlx.DB
    
    type user struct {
     ID       int    `json:"id"`
     Username string `json:"username"`
     Password string `json:"password"`
    }
    
    // InitDB 数据库初始化
    func InitDB() (err error) {
     dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse"
     // Connect 就是连接的同时db.ping()一下
     db, err = sqlx.Connect("mysql", dsn)
     CheckErr(err)
     db.SetMaxOpenConns(50)
     db.SetMaxIdleConns(10)
     fmt.Println("goUse 数据库连接成功")
     return
    }
    
    // SelectDB 查询单条数据的方法
    func SelectDB() {
     sqlStr := `select * from test where id=?`
     var data user
     _ = db.Get(data, sqlStr, 990)
     //CheckErr(err)
     fmt.Printf("%#v\n", data)
     marshal, err := json.Marshal(data)
     CheckErr(err)
     fmt.Println(string(marshal))
    }
    
    // ManySelect 查询多条数据方法
    func ManySelect() {
     sqlStr := `select * from test where id  ?`
     var dataList []user
     err := db.Select(dataList, sqlStr, 1000)
     CheckErr(err)
     //fmt.Println(dataList)
     marshal, err := json.Marshal(dataList)
     CheckErr(err)
     fmt.Println(string(marshal))
    }
    
    //CheckErr 异常捕获函数
    func CheckErr(err error) {
     if err != nil {
      fmt.Println(err)
      panic(err)
     }
    }
    
    func main() {
     err := InitDB()
     CheckErr(err)
     SelectDB()
     ManySelect()
    
    }

    Go操作Redis

    安装go get -u github.com/go-redis/redis

    package main
    
    import (
     "fmt"
    
     "github.com/go-redis/redis"
    )
    
    var redisDB *redis.Client
    
    // InitRedisDB redis数据库初始化
    func InitRedisDB() (err error) {
    
     redisDB = redis.NewClient(redis.Options{
      Addr:     "127.0.0.1:6379",
      Password: "",
      DB:       0,
     })
     _, err = redisDB.Ping(redisDB.Context()).Result()
     CheckErr(err)
     fmt.Println("redis 连接成功")
     return
    }
    
    //CheckErr 异常捕获函数
    func CheckErr(err error) {
     if err != nil {
      fmt.Println(err)
      panic(err)
     }
    }
    
    func main() {
     _ = InitRedisDB()
    }
    
    

    NSQ分布式消息队列

    NSQ是目前比较流行的一个分布式消息队列,下面主要是NSQ及GO语言如何操作NSQ

    NSQ是GO语言编写的一个开源的实时分布式内存消息队列, 其性能十分优异, NSQ的优势有:

    ​ 1.NSQ提倡分布式和扩散的拓扑,没有单点故障,支持容错和高可用性,并提供可靠的消息交付保证

    ​ 2.NSQ支持横向扩展, 没有任何集中式代理

    ​ 3.NSQ易于配置和部署,并且内置了管理界面

    安装go get -u github.com/nsqio/go-nsq

    Context

    在Go HTTP 包的server中,每一个请求都在对应着一个响应,请求处理函数通常会启动额外的goroutine用来访问后端的服务,比如数据库和rpc服务,用来处理一个请求的goroutine通常需要访问一些与请求特定的数据,比如终端的身份认证信息、验证相关的token、请求和截止时间。当一个请求被取消或超时时,所有用来处理该请求的goroutine都应该迅速退出,然后系统才能释放这些goroutine

    如何优雅的结束goroutine释放资源

    // 通道版本
    package main
    
    import (
     "fmt"
     "sync"
     "time"
    )
    
    var wg sync.WaitGroup
    
    func worker(exitChan -chan struct{}) {
     defer wg.Done()
    Test:
     for {
      fmt.Println("worker")
      time.Sleep(time.Second)
      select {
      case -exitChan:
       break Test
      default:
      }
    
     }
    
    }
    
    func main() {
     wg.Add(1)
     c := make(chan struct{})
    
     go worker(c)
     time.Sleep(10 * time.Second)
     c - struct{}{}
     close(c)
     wg.Wait()
     fmt.Println("Over")
    
    }
    
    // Context版本
    package main
    
    import (
     "context"
     "fmt"
     "sync"
     "time"
    )
    
    var wg sync.WaitGroup
    
    func worker(ctx context.Context) {
     defer wg.Done()
    Test:
     for {
      fmt.Println("worker")
      time.Sleep(time.Second)
      select {
      case -ctx.Done():
       break Test
      default:
      }
    
     }
    
    }
    
    func main() {
     wg.Add(1)
     ctx, cancelFunc := context.WithCancel(context.Background())
    
     go worker(ctx)
     time.Sleep(10 * time.Second)
    
     cancelFunc()
     wg.Wait()
     fmt.Println("Over")
    }

    如果goroutine开启了新的goroutine,只需要将ctx传入到新的goroutine中即可

    Background() 和 TODO()

    go内置两个函数: Background() 和TUDO(),这两个函数分别返回了一个实现了context接口的background和todo. 我们代码中最开始都是以这两个内置的上下文对象作为最顶层的partent context,衍生出更多的子上下文对象。

    backgroud() 主要用于main函数,初始化以及代码测试,作为context这个树结构的最顶层context,也就是跟context。

    todo(),他目前还不知道能干点啥?

    使用context的注意事项

    log标准库

    log包定义了Logger类型, 该类型提供了一些格式化输出的方法。本包也提供了一个预定义的标准logger,可以通过调用函数Print系列,fatal系列和panic系列来使用,比自行创建的logger对象更容易使用。

    package main
    
    import "log"
    
    func main() {
     log.Println("这是第一条工作日志")
    
     v := "THIS is worker log"
     log.Printf("%#v\n", v)
     // Fatal将会值写入信息之后,执行exit(1)
     log.Fatal("之后写一万行代码 我也不执行了哦")
    
     // 可以通过log.Panic 引发异常 会将日志写入之后引发异常
     log.Panic("测试panic的日志")
    
    }
    
    

    flag选项(日志输出内容设置)

    log标准库提供了如下的flag选项,他们是一系列定义好的常量。

    const (
     Ldate = 1  iota
      Ltime
      Lmicroseconds
      Llongfile
      Lshortfile
      LUTC
      LstdFlags = Ldate | Ltime
    )
    
    
    
    package main
    import "log"
    func main() {
        // 设置默认附加的内容 
      log.SetFlags(log.Llongfile | log.Ltime)
        // 设置日志前缀
      log.SetPrefix("[go_log] ")
      log.Println("测试日志")
    
    }
    output>>>
    [go_log] 19:02:14 /Users/mac/GolandProjects/src/day02/go_log库/main.go:19: 测试日志
    

    配置日志输出位置

    setoutput函数用来设置logger的输出目的地,默认是标准错误输出

    package main
    
    import (
     "log"
     "os"
    )
    
    func main() {
    
     file, err := os.OpenFile("test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
     if err != nil {
      log.Panic("文件打开失败")
     }
      // 设置了写入文件 日志内容就不会打印到终端了
     log.SetOutput(file)
     log.SetFlags(log.Llongfile | log.Ltime)
     log.SetPrefix("[go_log] ")
     log.Println("测试日志")
    
    }

    我们可以定义一个init初始化函数 将log全部配置好 这样更加标准化

    第三方日志库logrus的使用

    logrus是GO结构化的logger 与上边的logger标准库完全兼容

    安装logrusgo get github.com/sirupsen/logrus

    package main
    
    import (
     log "github.com/sirupsen/logrus"
    )
    
    func main() {
     log.WithFields(log.Fields{
      "animals": "dog",
      "time":    log.FieldKeyTime,
     }).Info("这是啥")
    }

    日志级别

    Trace、debug、info、warning、error、fatal、panic

     log.Trace("跟踪?")
     log.Debug("Debug?")
     log.Info("信息")
     log.Warn("警告?")
     log.Error("Something failed but I'm not quitting.")
     // 记完日志后会调用os.Exit(1) 
     log.Fatal("Bye.")
     // 记完日志后会调用 panic() 
     log.Panic("I'm bailing.")
    
    

    日志记录

    package main
    
    import (
     "os"
     "time"
    
     log "github.com/sirupsen/logrus"
    )
    
    func main() {
     file, err := os.OpenFile("logrustest.log", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
     if err != nil {
      log.Panicln(err)
     }
     log.SetOutput(file)
     for i := 0; i  100; i++ {
      log.WithFields(log.Fields{
       "animals": "dog",
       "Countey": "China",
       "City":    "BeiJing",
      }).Info("这是啥")
      time.Sleep(time.Second)
     }
    
     log.Trace("跟踪?")
     log.Info("信息")
     log.Warn("警告?")
     // 设置日志级别, 会记录info以上级别(warn error fatal panic)
     log.SetLevel(log.InfoLevel)
    
    }
    
    >>>结果
    time="2021-02-04T12:00:15+08:00" level=info msg="这是啥" City=BeiJing Countey=China animals=dog
    time="2021-02-04T12:00:17+08:00" level=info msg="这是啥" City=BeiJing Countey=China animals=dog
    time="2021-02-04T12:00:18+08:00" level=info msg="这是啥" City=BeiJing Countey=China animals=dog
    time="2021-02-04T12:00:19+08:00" level=info msg="这是啥" City=BeiJing Countey=China animals=dog

    日志的条目除了使用withfield 和withfields添加的相关日志,还有一些默认添加的日志字段

    time 记录日志的时间戳 msg 记录日志信息 level记录日志级别

    日志格式化

    logrus内置一下两种日志格式化程序

    logrus.TextFormatter logrus.JSONFormatter

    log.SetFormatter(log.JSONFormatter{})
    

    追踪函数

     log.SetReportCaller(true)

    这样就会将哪个文件哪一行 都记录下来  但是不是特殊需求无需开启这个 因为会增加性能开

    到此这篇关于Go语言操作数据库及其常规操作的示例代码的文章就介绍到这了,更多相关Go语言操作数据库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • go语言静态库的编译和使用方法
    • Go语言-为什么返回值为接口类型,却返回结构体
    • Go语言利用ssh连接服务器的方法步骤
    • 详解用Go语言实现工厂模式(Golang经典编程案例)
    • Go语言reflect.TypeOf()和reflect.Type通过反射获取类型信息
    • go语言实现简易比特币系统之交易签名及校验功能
    • Go语言编译程序从后台运行,不出现dos窗口的操作
    上一篇:Go语言利用ssh连接服务器的方法步骤
    下一篇:详解go中panic源码解读
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Go语言操作数据库及其常规操作的示例代码 语言,操作,数据库,及其,