Go 操作 MySQL 数据库

389 阅读3分钟

0. 背景

在实际开发中,要用到数据库存储数据。MySQL是一个关系型数据库管理系统 使用非常广泛。在Go语言开发中,会选择一个操作数据的类库来帮助我们完成工作。

1. 简单介绍

1.1 MySQL 数据库介绍

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。

1.2 Go 语言标准库中的 database/sql 包介绍

database/sql 包提供了一个围绕sql(或类似sql)数据库的通用接口

中文 API 文档地址:studygolang.com/pkgdoc

2. 操作 MySQL 数据库的准备工作

2.1 加载驱动

操作mysql需要 mysql 的驱动,由于我使用 go mod 来管理依赖,直接导入包就行。

  import (
    _ "github.com/go-sql-driver/mysql"
  )

然后执行 go mod vendor 来同步更新,这时 go mod 会自动更新 go.mod文件和下载依赖包

go mod vendor

2.2 导入 包

方法同上,导入包即可。

import "database/sql"

2.3 打开数据库

调用 sql.Open 方法打开数据库

db, err := sql.Open("mysql", dataSourceName)
defer db.Close()
if err != nil {
return
}

在执行了Open 后,并没有立即建立数据库连接。直到你发起数据库请求后才真正建立连接。 你可以使用 Ping 来验证连接是否通畅。

2.4 验证连接是否通畅

if err := db.Ping(); err != nil {
    log.Fatal(err)
} else {
    fmt.Println("连接成功")
}

3. 一些基本操作

3.1 增(插入数据)

使用 db.Exec 方法插入数据,执行后 result.RowsAffected 指示了影响的行数。

result, err := db.Exec("INSERT INTO account_infos(name,password) VALUES(?,?)", "WANG567", "FSFDS")
    if result != nil {
        //插入数据后的主键id
        lastInsertID, _ := result.LastInsertId()
        //影响行数
        rowsaffected, _ := result.RowsAffected()
        fmt.Println("#INSERT lastInsertID=", lastInsertID, "RowsAffected=", rowsaffected)
    }

3.2 查询

使用 db.Query 方法 执行查询SQL,rows.Next 方法遍历结果集,rows.Scan 读取数据到指定的变量中。


    //查询数据库
    rows, err := db.Query("select name,password from account_infos ")
    if err != nil {
        log.Fatal(err)
    }
    for rows.Next() {
        var name, pwd string
        rows.Scan(&name, &pwd)
        fmt.Println("name=", name, "pwd=", pwd)
    }

3.3 预处理SQL

使用 db.Prepare 方法 返回一个 预处理后的 stmt (statement), stmt 可以多次执行。

    // 预处理sql
    stmt,err := db.Prepare("select name,password from account_infos where name=? ")
    if err != nil {
        log.Fatal(err)
    }
    rows2, err := stmt.Query("zhangyunfei")
    if err != nil {
        log.Fatal(err)
    }
    for rows2.Next() {
        var name, pwd string
        rows2.Scan(&name, &pwd)
        fmt.Println("name=", name, "pwd=", pwd)
    }

3.4 改 (更新)

使用 db.Exec 执行 SQL 预计,执行后同构 result3.RowsAffected()
获得 影响行数。

    // 更新 (update)
    result3, err := db.Exec("update account_infos set password=? where name=?", "hello", "WANG567")
    if err != nil {
        fmt.Println("ERROR:", err)
        log.Fatal(err)
    }
    if result3 != nil {
        //插入数据后的主键id
        lastInsertID, _ := result3.LastInsertId()
        //影响行数
        rowsaffected, _ := result3.RowsAffected()
        fmt.Println("#UPDATE lastInsertID=", lastInsertID, "RowsAffected=", rowsaffected)
    }

3.5 删 (删除数据)

使用 db.Exec 执行删除SQL语句,判断 result.RowsAffected() 影响行数。

    // 删除 (delete)
    result4, err := db.Exec("delete from account_infos where name=?", "WANG567")
    if err != nil {
        fmt.Println("ERROR:", err)
        log.Fatal(err)
    }
    if result4 != nil {
        //插入数据后的主键id
        lastInsertID, _ := result3.LastInsertId()
        //影响行数
        rowsaffected, _ := result3.RowsAffected()
        fmt.Println("#DELETE lastInsertID=", lastInsertID, "RowsAffected=", rowsaffected)
    }

3.6 事务

数据库事务需要注意几点:

  • 事务的开启
  • 事务的终止方式之一,提交
  • 事务的终止方式之二,回滚

db.Begin() 开始一个事务,然后就可以指定多条你需要集中在一个事务中执行的多条SQL指令,在结束时根据你期望的条件是否达成来决定是提交或者回滚(丢弃)

    // 事务
    tx, err := db.Begin() //启用一个事务
    result5, err := tx.Exec("delete from account_infos where name=?", "WANG567")
    ok1, _ := result5.RowsAffected()
    result6, err := tx.Exec("delete from account_infos where name=?", "WANG567")
    ok2, _ := result6.RowsAffected()
    if ok1 > 0 && ok2 > 0 {
        tx.Commit() // 提交事物
    } else {
        tx.Rollback() // 回退
    }

4. 参考

github.com/golang/go/w…
github.com/golang/go/w…
studygolang.com/pkgdoc

END