• Go语言操作MySQL数据库


    Go语言操作MySQL数据库

    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。
    
    Go语言MySQL包
    使用第三方开源的mysql库:
    
    github.com/go-sql-driver/mysql (MySQL驱动)
    github.com/jmoiron/sqlx (基于MySQL驱动的封装)
     
    通过如下命令,保存下载第三方库:
    go get github.com/go-sql-driver/mysql
    go get github.com/jmoiron/sqlx 
    
    创建数据库、数据表
    在MySQL下创建 oldboy库:
    mysql> CREATE DATABASE IF NOT EXISTS oldboy DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    
    在oldboy库中创建student表。
    mysql> use oldboy;
    
    mysql> CREATE TABLE IF NOT EXISTS `student`(
        `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
        `name` varchar(100) NOT NULL,
        `sex` varchar(40) NOT NULL,
        `age` int(11) DEFAULT NULL,
        `course` varchar(100) NOT NULL,
        PRIMARY KEY (`id`)
    )ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    MySQL连接池
    数据库连接使用datebase/sql Open函数进行连接,用户应该通过db.Ping()函数来检查数据库是否实际可用。
    
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    func main() {
        //DB, err := sqlx.Open("数据库类型", "用户名:密码@tcp(地址:端口)/数据库名")
        DB, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
        if err != nil {
            fmt.Println("Open mysql failed,", err)
        }
        err = DB.Ping()
        if err != nil {
            fmt.Println("Ping mysql failed,", err)
        } else {
            fmt.Println("MySQL client success")
        }
    }
    
    
    连接池配置
    配置连接池有两个的函数:
    设置最大数据库连接:使用 db.SetMaxOpenConns(n int) 函数设置打开数据库的最大连接数。包含正在使用的连接和连接池的连接。如果你的函数调用需要申请一个连接,并且连接池已经没有了连接或者连接数达到了最大连接数。此时的函数调用将会被block,直到有可用的连接才会返回。设置这个值可以避免并发太高导致连接mysql出现too many connections的错误。该函数的默认设置是0,表示无限制。
    设置最大空闲连接:使用db.SetMaxIdleConns(n int) 函数设置连接池中的保持连接的最大连接数。默认也是0,表示连接池不会保持释放会连接池中的连接的连接状态:即当连接释放回到连接池的时候,连接将会被关闭。这会导致连接再连接池中频繁的关闭和创建。
    
    
    
    插入操作
    建议使用结构化操作,不推荐使用直接拼接sql语句的方法。
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Student struct {
        Id     int    `db:"id"`
        Name   string `db:"name"`
        Sex    string `db:"sex"`
        Age    int    `db:"age"`
        Course string `db:"course"`
    }
    
    var Db *sqlx.DB
    
    func init() {
        database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
        Db = database
    }
    
    func main() {
        r, err := Db.Exec("insert into student(name, sex, age, course)values(?, ?, ?, ?)", "张三", "", 18, "Golang")
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
        id, err := r.LastInsertId()
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
    
        fmt.Println("insert succ:", id)
    }
    
    
    
    查询操作
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Student struct {
        Id     int    `db:"id"`
        Name   string `db:"name"`
        Sex    string `db:"sex"`
        Age    int    `db:"age"`
        Course string `db:"course"`
    }
    
    var Db *sqlx.DB
    
    func init() {
        database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
        Db = database
    }
    
    func main() {
        var student []Student
        err := Db.Select(&student, "select id, name, sex, age, course from student where course=?", "Golang")
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
    
        fmt.Println("select succ:", student)
    }
    
    
    
    修改操作
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Student struct {
        Id     int    `db:"id"`
        Name   string `db:"name"`
        Sex    string `db:"sex"`
        Age    int    `db:"age"`
        Course string `db:"course"`
    }
    
    var Db *sqlx.DB
    
    func init() {
        database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
        Db = database
    }
    
    func main() {
        res, err := Db.Exec("update student set name=? where course=?", "李四", "Golang")
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
        row, err := res.RowsAffected()
        if err != nil {
            fmt.Println("rows failed, ", err)
        }
        fmt.Println("update succ:", row)
    }
    
    
    
    删除操作
    package main
    
    import (
        "fmt"
     
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Student struct {
        Id     int    `db:"id"`
        Name   string `db:"name"`
        Sex    string `db:"sex"`
        Age    int    `db:"age"`
        Course string `db:"course"`
    }
    
    var Db *sqlx.DB
    
    func init() {
        database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
        Db = database
    }
    
    func main() {
        res, err := Db.Exec("delete from student where name=?", "李四")
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
    
        row, err := res.RowsAffected()
        if err != nil {
            fmt.Println("rows failed, ", err)
        }
    
        fmt.Println("delete succ: ", row)
    }
    修改和删除操作都比较简单,同插入数据类似,只是使用RowsAffected来获取影响的数据行数。
    
    
    
    MySQL事务
    MySQL 事务主要用于处理操作量大,复杂度高的数据。
    在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
    事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
    事务用来管理 insert,update,delete 语句
    一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
    
    Go语言MySQL事务应用包与函数:
    1) import ("github.com/jmoiron/sqlx")
    2)  conn, err := Db.Begin()    开始事务
    3)  conn.Commit()              提交事务
    4)  conn.Rollback()            回滚事务
    
    
    事务应用
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Student struct {
        Id     int    `db:"id"`
        Name   string `db:"name"`
        Sex    string `db:"sex"`
        Age    int    `db:"age"`
        Course string `db:"course"`
    }
    
    var Db *sqlx.DB
    
    func init() {
        database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/oldboy")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
        Db = database
    }
    
    func main() {
        conn, err := Db.Begin()
        if err != nil {
            fmt.Println("begin failed :", err)
            return
        }
    
        r, err := Db.Exec("insert into student(name, sex, age, course)values(?, ?, ?, ?)", "王五", "", 18, "Golang")
        if err != nil {
            fmt.Println("exec failed, ", err)
            conn.Rollback()
            return
        }
        id, err := r.LastInsertId()
        if err != nil {
            fmt.Println("exec failed, ", err)
            conn.Rollback()
            return
        }
        fmt.Println("insert succ:", id)
    
        r, err = Db.Exec("insert into student(name, sex, age, course)values(?, ?, ?, ?)", "赵六", "", 18, "Linux、Python、Java")
        if err != nil {
            fmt.Println("exec failed, ", err)
            conn.Rollback()
            return
        }
        id, err = r.LastInsertId()
        if err != nil {
            fmt.Println("exec failed, ", err)
            conn.Rollback()
            return
        }
        fmt.Println("insert succ:", id)
    
        conn.Commit()
    }
    
    查看MySQL:
    mysql> select id,name,sex,age,course from student;
    +----+--------+-----+------+-----------------------+
    | id | name   | sex | age  | course                |
    +----+--------+-----+------+-----------------------+
    |  2 | 王五   | 男  |   18 | Golang                |
    |  3 | 赵六   | 男  |   18 | Linux、Python、Java   |
    +----+--------+-----+------+-----------------------+
    2 rows in set (0.00 sec)
    
    
    
    Go语言操作mysql除使用 github.com/go-sql-driver/mysql第三方开源的mysql库外还可以使用github.com/jinzhu/gorm包,GORM是使用Go语言开发的友好的ORM库。
    
    安装
    go get -u github.com/jinzhu/gorm
    
    通用数据库接口sql.DB
    从*gorm.DB连接获取通用数据库接口*sql.DB
    
    // 获取通用数据库对象`*sql.DB`以使用其函数
    db.DB()
    
    // Ping
    db.DB().Ping()
    
    连接池
    db.DB().SetMaxIdleConns(10)
    db.DB().SetMaxOpenConns(100)
    
    复合主键
    将多个字段设置为主键以启用复合主键
    
    type Product struct {
        ID           string `gorm:"primary_key"`
        LanguageCode string `gorm:"primary_key"`
    }
    
    
    日志
    Gorm有内置的日志记录器支持,默认情况下,它会打印发生的错误
    
    // 启用Logger,显示详细日志
    db.LogMode(true)
    
    // 禁用日志记录器,不显示任何日志
    db.LogMode(false)
    
    // 调试单个操作,显示此操作的详细日志
    db.Debug().Where("name = ?", "jinzhu").First(&User{})
    
    自定义日志
    参考GORM的默认记录器如何自定义
    https://github.com/jinzhu/gorm/blob/master/logger.go
    
    db.SetLogger(gorm.Logger{revel.TRACE})
    db.SetLogger(log.New(os.Stdout, "
    ", 0))
    
    
    
    架构
    Gorm使用可链接的API,*gorm.DB是链的桥梁,对于每个链API,它将创建一个新的关系。
    db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")
    
    // 创建新关系
    db = db.Where("name = ?", "jinzhu")
    
    // 过滤更多
    if SomeCondition {
        db = db.Where("age = ?", 20)
    } else {
        db = db.Where("age = ?", 30)
    }
    if YetAnotherCondition {
        db = db.Where("active = ?", 1)
    }
    当我们开始执行任何操作时,GORM将基于当前的*gorm.DB创建一个新的*gorm.Scope实例
    
    // 执行查询操作
    db.First(&user)
    并且基于当前操作的类型,它将调用注册的creating,updating,querying,deleting或row_querying回调来运行操作。
  • 相关阅读:
    史上最走心的Webpack4.0中级教程——配置之外你应该知道事
    javascript基础修炼(11)——DOM-DIFF的实现
    一统江湖的大前端(7)React.js-从开发者到工程师
    express中间件系统的基本实现
    js中如何在不影响既有事件监听的前提下新增监听器
    Zabbix的应用(6)----常见错误
    Ansible初级应用
    一个好用的小工具 thefuck
    使用python读取word文件里的表格信息
    01010_Eclipse中项目的jar包导入与导出
  • 原文地址:https://www.cnblogs.com/zhouwanchun/p/10739950.html
Copyright © 2020-2023  润新知