Go Web编程(四)—— 访问MySQL数据库 | 青训营笔记

93 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天

本文介绍如何使用Go来连接MySQL数据库

MySQL的具体使用,例如建库建表和SQL语法就不赘述了

Go中使用MySQL

下载需要的包

 $ go get github.com/go-sql-driver/mysql 
 $ go get github.com/jmoiron/sqlx

前一个是MySQL的驱动,后一个是基于MySQL驱动的封装

连接MySQL数据库的操作

database, err := sqlx.Open("mysql","root:XXX@tcp(127.0.1:3306)/test")
//database, err := sqlx.Open("数据库类型", "用户名:密码@tcp(地址:端口)/数据库名")

Insert

首先导包,导入MySQL驱动

package main

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

定义数据结构体

type Person struct {
    UserId   int    `db:"user_id"`
    Username string `db:"username"`
    Sex      string `db:"sex"`
    Email    string `db:"email"`
}

在init()函数中连接数据库,需要将*sqlx.DB作为全局变量使用

var Db *sqlx.DB

func init() {

    database, err := sqlx.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }
    Db = database
    defer Db.Close()  // 注意这行代码要写在上面err判断的下面
    // 代表延迟关闭数据库(退出init()时关闭数据库,防止资源泄露)
}

实现简单的插入操作

func main() {

    r, err := Db.Exec("INSERT INTO person(username, sex, email)VALUES(?, ?, ?)", "stu001", "man", "stu01@qq.com")
    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)
}

或者使用Db.Prepare() + stmt.Exec()函数

stmt, err := Db.Prepare("INSERT ....")
if err != nil {
    // 错误处理
}
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
if err != nil { 
    // 错误处理
}

Db.Prepare () 函数用来返回准备要执行的 sql 操作,然后返回准备完毕的执行状态。

stmt.Exec () 函数用来执行 stmt 准备好的 SQL 语句

我们传入的参数都是 =? 对应的数据,这样做的方式可以一定程度上防止 SQL 注入。

Select

导包、init()函数、结构体定义与Insert中相同

查询单行数据

使用Db.Get()函数,接口如下

func (db *DB) Get(dest interface{}, query string, args ...interface{}) error

dest接收查询结果,query是查询语句,args为参数赋值

func main() {

    var person Person
    err := Db.Get(&person,"SELECT user_id, username FROM person WHERE user_id = ?", 1)
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }
    fmt.Println("select succ:", person)
}

查询多行数据

使用Db.Select()函数,接口如下

func (db *DB) Select(dest interface{}, query string, args ...interface{}) error

func main() {

    var person []Person
    err := Db.Select(&person, "SELECT user_id, username, sex, email FROM person WHERE user_id > ?", 0)
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }

    fmt.Println("select succ:", person)
}

Update

func main() {

    res, err := Db.Exec("UPDATE person SET username=? WHERE user_id=?", "stu0003", 1)
    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)

}

Delete

func main() {

    res, err := Db.Exec("DELETE FROM person WHERE user_id=?", 1)
    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)
}

不使用sqlx包

sqlx是 Go 的软件包,它在内置database/sql包的基础上提供了一组扩展。

该库兼容sql原生包,同时又提供了更为强大的、优雅的查询、插入函数。前文的示例使用了sqlx包的处理函数

如果不使用sqlx包,则使用func sql.Open(driverName, dataSourceName string) (*DB, error)打开数据库(打开一个注册过的数据库驱动),第二个参数dataSourceName支持很多格式,如下

image.png 例如

Db, err := sql.Open("mysql", "root:XXX@tcp(localhost:3306)/test")

通常情况 Open 函数只需调用一次,并很少需要关闭。若需要显式关闭,使用函数 func (db *DB) Close() error 完成,前文的代码中init()函数中的``

插入、更新、删除操作sqlx和原生sql一样,参考前文代码即可

查询操作有不一样的地方

Select

查询多行

rows, err := Db.Query("SELECT * FROM person")

查询单行

var username string
err := Db.QueryRow("SELECT ... WHERE id=?", 100).Scan(&username)

函数 func (db *DB) QueryRow(query string, args ...interface{}) *Row 执行查询操作,返回一行 sql.Row 类对象,参数 query 为查询 SQL。args 为 query 中占位参数

得到的 sql.Row 对象为单行结果集,需要使用 func (r *Row) Scan(dest ...interface{}) error 函数获取结果集中某个字段数据。如果该查询匹配多行,Scan 会使用第一行结果并丢弃其余各行,如果没有匹配查询的行,Scan 会返回 ErrNoRows。


参考资料

go操作MySQL · Go语言中文文档 (topgoer.com)

05.0 访问数据库 | 第五章. 访问数据库 |《Go Web 编程》| Go 技术论坛 (learnku.com)

Go语言中操作MySQL - 知乎 (zhihu.com)