golang操作MySQL数据库总结

本文视频链接:https://www.bilibili.com/vide...

关注公众号,下载课程材料和源码:

筹备数据库和表

下载安装MySQL

https://dev.mysql.com/downloads/mysql/

创立一个go_db数据库

create database go_db

关上数据库

use go_db

创立表

CREATE TABLE user_tbl (  id INTEGER PRIMARY KEY AUTO_INCREMENT,  username VARCHAR (20),  PASSWORD VARCHAR (20))

增加模仿数据

INSERT INTO user_tbl (username, PASSWORD) VALUES ("tom", "123")INSERT INTO user_tbl (username, PASSWORD) VALUES ("kite", "456")

装置配置mysql驱动

装置驱动

go get -u github.com/go-sql-driver/mysql

初始化模块

go mod init m

执行go mod tidy

go mod tidy

导入驱动

package mainimport (    "fmt"    "database/sql"    _ "github.com/go-sql-driver/mysql")func main() {    }

取得数据库连贯

导入包

package mainimport (    "fmt"    "database/sql"    _ "github.com/go-sql-driver/mysql")

取得连贯

package mainimport (    "database/sql"    _ "github.com/go-sql-driver/mysql"    "time")func main() {    db, err := sql.Open("mysql", "root:123456@/go_db")    if err != nil {        panic(err)    }    print(db)    // 最大连贯时长    db.SetConnMaxLifetime(time.Minute * 3)    // 最大连接数    db.SetMaxOpenConns(10)    // 闲暇连接数    db.SetMaxIdleConns(10)}

初始化连贯

Open函数可能只是验证其参数格局是否正确,实际上并不创立与数据库的连贯。如果要查看数据源的名称是否真实有效,应该调用Ping办法。

返回的DB对象能够平安地被多个goroutine并发应用,并且保护其本人的闲暇连接池。因而,Open函数应该仅被调用一次,很少须要敞开这个DB对象。

package mainimport (    "database/sql"    "fmt"    _ "github.com/go-sql-driver/mysql")// 定义一个全局对象dbvar db *sql.DB// 定义一个初始化数据库的函数func initDB() (err error) {    dsn := "root:123456@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4&parseTime=True"    // 不会校验账号密码是否正确    // 留神!!!这里不要应用:=,咱们是给全局变量赋值,而后在main函数中应用全局变量db    db, err = sql.Open("mysql", dsn)    if err != nil {        return err    }    // 尝试与数据库建设连贯(校验dsn是否正确)    err = db.Ping()    if err != nil {        return err    }    return nil}func main() {    err := initDB() // 调用输入化数据库的函数    if err != nil {        fmt.Printf("初始化失败!,err:%v\n", err)        return    }else{        fmt.Printf("初始化胜利")    }}

查问操作

单行查问

单行查问db.QueryRow()执行一次查问,并冀望返回最多一行后果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan办法被调用时,才会返回被提早的谬误。

定义一个构造体

type user struct {    id int    username string    password string}

查问

// 查问一条用户数据func queryRowDemo() {    sqlStr := "select id, username, password from user_tbl where id=?"    var u user    // 确保QueryRow之后调用Scan办法,否则持有的数据库链接不会被开释    err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.username, &u.password)    if err != nil {        fmt.Printf("scan failed, err:%v\n", err)        return    }    fmt.Printf("id:%d name:%s age:%s\n", u.id, u.username, u.password)}

测试

func main() {    err := initDB() // 调用输入化数据库的函数    if err != nil {        fmt.Printf("初始化失败!,err:%v\n", err)        return    }else{        fmt.Printf("初始化胜利")    }    queryRowDemo()}

运行后果

初始化胜利id:1 name:tom age:123

查问多行

多行查问db.Query()执行一次查问,返回多行后果(即Rows),个别用于执行select命令。参数args示意query中的占位参数。

// 查问多条数据示例func queryMultiRow() {    sqlStr := "select id, username, password from user_tbl where id > ?"    rows, err := db.Query(sqlStr, 0)    if err != nil {        fmt.Printf("query failed, err:%v\n", err)        return    }    // 十分重要:敞开rows开释持有的数据库链接    defer rows.Close()    // 循环读取后果集中的数据    for rows.Next() {        var u user        err := rows.Scan(&u.id, &u.username, &u.password)        if err != nil {            fmt.Printf("scan failed, err:%v\n", err)            return        }        fmt.Printf("id:%d username:%s password:%s\n", u.id, u.username, u.password)    }}

运行后果

初始化胜利id:1 username:tom password:123id:2 username:kite password:456

插入数据

插入、更新和删除操作都应用Exec办法。

func (db *DB) Exec(query string, args ...interface{}) (Result, error)
// 插入数据func insertData() {    sqlStr := "insert into user_tbl(username,password) values (?,?)"    ret, err := db.Exec(sqlStr, "张三", "zs123")    if err != nil {        fmt.Printf("insert failed, err:%v\n", err)        return    }    theID, err := ret.LastInsertId() // 新插入数据的id    if err != nil {        fmt.Printf("get lastinsert ID failed, err:%v\n", err)        return    }    fmt.Printf("insert success, the id is %d.\n", theID)}

测试

func main() {    err := initDB() // 调用输入化数据库的函数    if err != nil {        fmt.Printf("初始化失败!,err:%v\n", err)        return    }else{        fmt.Printf("初始化胜利\n")    }    //queryRowDemo()    //queryMultiRow()    insertData()}

运行后果

初始化胜利insert success, the id is 3.

删除数据

插入、更新和删除操作都应用Exec办法。

func (db *DB) Exec(query string, args ...interface{}) (Result, error)

删除

func delData()  {    sql := "delete from user_tbl where id =?"    ret, err := db.Exec(sql, "1")    if err != nil {        fmt.Printf("删除失败, err:%v\n", err)        return    }    rows, err := ret.RowsAffected()    if err != nil {        fmt.Printf("删除行失败, err:%v\n", err)        return    }    fmt.Printf("删除胜利, 删除的行数: %d.\n", rows)}

测试

func main() {    err := initDB() // 调用输入化数据库的函数    if err != nil {        fmt.Printf("初始化失败!,err:%v\n", err)        return    }else{        fmt.Printf("初始化胜利\n")    }    delData()}

运行后果

初始化胜利删除胜利, 删除的行数: 1.

更新数据

插入、更新和删除操作都应用Exec办法。

func (db *DB) Exec(query string, args ...interface{}) (Result, error)

更新

func updateData()  {    sql := "update user_tbl set username=?, password=? where id=?"    ret, err := db.Exec(sql, "kite2", "kite123", "2")    if err != nil {        fmt.Printf("更新失败, err:%v\n", err)        return    }    rows, err := ret.RowsAffected()    if err != nil {        fmt.Printf("更新行失败, err:%v\n", err)        return    }    fmt.Printf("更新胜利, 更新的行数: %d.\n", rows)}

测试

func main() {    err := initDB() // 调用输入化数据库的函数    if err != nil {        fmt.Printf("初始化失败!,err:%v\n", err)        return    }else{        fmt.Printf("初始化胜利\n")    }    //queryRowDemo()    //queryMultiRow()    //insertData()    //delData()    updateData()}

运行后果

初始化胜利更新胜利, 更新的行数: 1.