• Go语言学习笔记—golang操作MySQL数据库



    一 准备数据库和表

    创建一个go_db数据库

    create database go_db;
    
    • 1

    打开数据库

    use go_db;
    
    • 1

    创建表

     create table user_tb1(
         id integer primary key auto_increment,
         username varchar(20),
         password varchar(20)
     );
    
    • 1
    • 2
    • 3
    • 4
    • 5

    添加模拟数据

    insert into user_tb1(username,password) value("psych","666");
    insert into user_tb1(username,password) value("tom","123");
    insert into user_tb1(username,password) value("kitte","456");
    
    • 1
    • 2
    • 3

    详细过程:

    C:\Users\Mechrevo>mysql -uroot -p
    Enter password: ******
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 10
    Server version: 8.0.19 MySQL Community Server - GPL
    
    Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> create database go_db;
    Query OK, 1 row affected (0.44 sec)
    
    mysql> use go_db;
    Database changed
    
    mysql> create table user_tb1(id integer primary key auto_increment,username varchar(20),password varchar(20));
    Query OK, 0 rows affected (1.10 sec)
    
    mysql> desc user_tb1;
    +----------+-------------+------+-----+---------+----------------+
    | Field    | Type        | Null | Key | Default | Extra          |
    +----------+-------------+------+-----+---------+----------------+
    | id       | int         | NO   | PRI | NULL    | auto_increment |
    | username | varchar(20) | YES  |     | NULL    |                |
    | password | varchar(20) | YES  |     | NULL    |                |
    +----------+-------------+------+-----+---------+----------------+
    3 rows in set (0.23 sec)
    
    mysql> insert into user_tb1(username,password) value("psych","666");
    Query OK, 1 row affected (0.47 sec)
    
    mysql> insert into user_tb1(username,password) value("tom","123");
    Query OK, 1 row affected (0.17 sec)
    
    mysql> insert into user_tb1(username,password) value("kitte","456");
    Query OK, 1 row affected (0.09 sec)
    
    mysql> select * from user_tb1;
    +----+----------+----------+
    | id | username | password |
    +----+----------+----------+
    |  1 | psych    | 666      |
    |  2 | tom      | 123      |
    |  3 | kitte    | 456      |
    +----+----------+----------+
    3 rows in set (0.03 sec)
    
    mysql>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    二 安装配置mysql驱动

    安装驱动

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

    初始化模块

    go mod init m
    
    • 1

    执行go mod tidy

    go mod tidy
    
    • 1

    导入驱动(官方示例https://pkg.go.dev/github.com/go-sql-driver/mysql@v1.6.0#section-readme)

    package main
    
    import (
    	"database/sql"
    	"time"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    func main() {
    	// ...
    
    	db, err := sql.Open("mysql", "user:password@/dbname")
    	if err != nil {
    		panic(err)
    	}
    	// See "Important settings" section.
    	db.SetConnMaxLifetime(time.Minute * 3)
    	db.SetMaxOpenConns(10)
    	db.SetMaxIdleConns(10)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    三 获得数据库连接

    3.1 导入包

    import (
    	"database/sql"
    	"time"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.2 获得连接

    package main
    
    import (
    	"database/sql"
    	"fmt"
    	"time"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // ...
    func main() {
    	db, err := sql.Open("mysql", "root:960690@/go_db")
    	if err != nil {
    		panic(err)
    	}
    	// 设置最大连接时长
    	db.SetConnMaxLifetime(time.Minute * 3)
        
    	// 设置最大连接数
    	db.SetMaxOpenConns(10)
    	
    	// 设置空闲连接数
    	db.SetMaxIdleConns(10)
    
    	fmt.Printf("db:%v\n", db)
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    db:&{0 0xc000006028 0 {0 0} [] map[] 0 0 0xc00005c0c0 false map[] map[] 10 10 180000000000 0 <nil> 0 0 0 0 0x54a100}
    
    [Done] exited with code=0 in 2.423 seconds
    
    • 1
    • 2
    • 3
    • 4

    3.3 初始化连接

    Open函数只是验证格式是否正确,实际上并不是创建数据库连接。如果要检查数据源的名称是否真实有效,应该调用Ping方法。

    返回的DB对象可以安全地被多个协程并发使用,并且维护其自己的空闲连接池。因此Open函数应该仅被调用一次,很少需要关闭这个DB对象。

    package main
    
    import (
    	"database/sql"
    	"fmt"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // 定义一个全局对象db
    var db *sql.DB
    
    // 定义一个初始化数据库的函数
    func initDB() (err error) {
    	// dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4&parseTime=True"
    	dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4"
    
    	db, err = sql.Open("mysql", dsn)
    	// 注意!!!这里不要使用:= 我们是给全局变量赋值,然后在main函数中使用全局变量db
    	// open函数只是验证格式是否正确,不会校验账号密码是否正确,并不是创建数据库连接
    	if err != nil {
    		return err
    	}
    
    	// 尝试与数据库建立连接,即校验dsn是否正确
    	err2 := db.Ping()
    	if err2 != nil {
    		return err2
    	}
    	return nil
    }
    
    func main() {
    	err := initDB() // 调用初始化数据库的函数
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    	} else {
    		fmt.Println("连接成功")
    	}
    	fmt.Printf("db: %v\n", db)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    连接成功
    db: &{0 0xc000006028 0 {0 0} [0xc00012e000] map[] 0 1 0xc00005c0c0 false map[0xc00012e000:map[0xc00012e000:true]] map[] 0 0 0 0 <nil> 0 0 0 0 0x30a5a0}
    
    [Done] exited with code=0 in 1.869 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5

    四 插入数据

    使用Exec方法

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

    实例演示1:

    package main
    
    import (
    	"database/sql"
    	"fmt"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // 定义一个全局对象db
    var db *sql.DB
    
    // 定义一个初始化数据库的函数
    func initDB() (err error) {
    	dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4"
    
    	db, err = sql.Open("mysql", dsn)
    	if err != nil {
    		return err
    	}
    
    	err2 := db.Ping()
    	if err2 != nil {
    		return err2
    	}
    	return nil
    }
    
    // 插入数据
    func insertData() {
    	sqlStr := "insert into user_tb1(username,password) values (?,?)"
    	ret, err := db.Exec(sqlStr, "Klee", "boomboomboom")
    	if err != nil {
    		fmt.Println("insert err = ", err)
    		return
    	}
    
    	theId, err := ret.LastInsertId() // 新插入的数据id
    	if err != nil {
    		fmt.Println("get LastInsertId err = ", err)
    		return
    	}
    	fmt.Printf("插入成功,id是: %d.\n", theId)
    }
    
    func main() {
    	err := initDB() // 调用初始化数据库的函数
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    	} else {
    		fmt.Println("数据库go_db连接成功")
    	}
    
    	insertData()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    数据库go_db连接成功
    插入成功,id是: 4.
    
    [Done] exited with code=0 in 1.657 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数据库查看:

    在这里插入图片描述

    实例演示2:

    package main
    
    import (
    	"database/sql"
    	"fmt"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // 定义一个全局对象db
    var db *sql.DB
    
    // 定义一个初始化数据库的函数
    func initDB() (err error) {
    	dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4"
    
    	db, err = sql.Open("mysql", dsn)
    	if err != nil {
    		return err
    	}
    
    	err2 := db.Ping()
    	if err2 != nil {
    		return err2
    	}
    	return nil
    }
    
    // 插入数据
    
    func insertData2(username string, password string) {
    	sqlStr := "insert into user_tb1(username,password) values (?,?)"
    	ret, err := db.Exec(sqlStr, username, password)
    	if err != nil {
    		fmt.Println("insert err = ", err)
    		return
    	}
    
    	theId, err := ret.LastInsertId() // 新插入的数据id
    	if err != nil {
    		fmt.Println("get LastInsertId err = ", err)
    		return
    	}
    	fmt.Printf("插入成功,id是: %d.\n", theId)
    }
    
    func main() {
    	err := initDB() // 调用初始化数据库的函数
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    	} else {
    		fmt.Println("数据库go_db连接成功")
    	}
    
    	insertData2("Morax", "yanwangdijun")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    数据库go_db连接成功
    插入成功,id是: 6.
    
    [Done] exited with code=0 in 1.673 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数据库查看:

    在这里插入图片描述

    五 查询数据

    5.1 单行查询

    db.QueryRow()执行一次查询,并期望返回最多一行结果。

    QueryRow总是返回非nil的值,知道返回值的Scan方法被调用时,才会返回延迟的错误。

    func (db *DB) QueryRow(query string, args ...any) *Row 
    
    • 1

    先定义一个结构体:

    type user struct {
    	id       int
    	username string
    	password string
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    实例演示:

    package main
    
    import (
    	"database/sql"
    	"fmt"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // 定义一个全局对象db
    var db *sql.DB
    
    // 定义一个初始化数据库的函数
    func initDB() (err error) {
    	dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4"
    
    	db, err = sql.Open("mysql", dsn)
    	if err != nil {
    		return err
    	}
    
    	err2 := db.Ping()
    	if err2 != nil {
    		return err2
    	}
    	return nil
    }
    
    type user struct {
    	id       int
    	username string
    	password string
    }
    
    func queryRowData() {
    	sqlStr := "select Id,username,password from user_tb1 where id=?"
    	var u user
    	err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.username, &u.password)
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    		return
    	}
    	fmt.Printf("Id:%d username:%v password:%v \n", u.id, u.username, u.password)
    }
    
    func main() {
    	err := initDB() // 初始化数据库
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    	} else {
    		fmt.Println("数据库go_db连接成功")
    	}
    	queryRowData()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    数据库go_db连接成功
    Id:1 username:psych password:666 
    
    [Done] exited with code=0 in 1.756 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.2 多行查询

    db.Query()执行一次查询,返回多行结果,一般用于执行select命令。

    参数args表示query中的占位参数。

    func (db *DB) Query(query string, args ...any) (*Rows, error)
    
    • 1

    实例演示:

    package main
    
    import (
    	"database/sql"
    	"fmt"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // 定义一个全局对象db
    var db *sql.DB
    
    // 定义一个初始化数据库的函数
    func initDB() (err error) {
    	dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4"
    
    	db, err = sql.Open("mysql", dsn)
    	if err != nil {
    		return err
    	}
    
    	err2 := db.Ping()
    	if err2 != nil {
    		return err2
    	}
    	return nil
    }
    
    type user struct {
    	id       int
    	username string
    	password string
    }
    
    func queryManyData() {
    	sqlStr := "select Id,username,password from user_tb1 where id > ?"
    	r, err := db.Query(sqlStr, 2)
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    		return
    	}
    	defer r.Close()	// 非常重要!!!关闭r释放持有的数据库连接
    
    	// 循环读取结果集中的数据
    	for r.Next() {
    		var u user
    		err2 := r.Scan(&u.id, &u.username, &u.password)
    		if err2 != nil {
    			fmt.Printf("err2: %v\n", err2)
    			return
    		}
    		fmt.Printf("Id:%d username:%v password:%v\n", u.id, u.username, u.password)
    	}
    }
    
    func main() {
    	err := initDB() // 初始化数据库
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    	} else {
    		fmt.Println("数据库go_db连接成功")
    	}
    	queryManyData()
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    数据库go_db连接成功
    Id:3 username:kitte password:456
    Id:4 username:Klee password:boomboomboom
    Id:6 username:Morax password:yanwangdijun
    
    [Done] exited with code=0 in 2.055 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    六 更新数据

    使用Exec方法

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

    实例演示:

    package main
    
    import (
    	"database/sql"
    	"fmt"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // 定义一个全局对象db
    var db *sql.DB
    
    // 定义一个初始化数据库的函数
    func initDB() (err error) {
    	dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4"
    
    	db, err = sql.Open("mysql", dsn)
    	if err != nil {
    		return err
    	}
    
    	err2 := db.Ping()
    	if err2 != nil {
    		return err2
    	}
    	return nil
    }
    
    func updateData() {
    	sql := "update user_tb1 set username=?,password=? where id=?"
    	ret, err := db.Exec(sql, "baal", "leishen", "3")
    	if err != nil {
    		fmt.Println("更新失败,err = ", err)
    		return
    	}
    	rows, err := ret.RowsAffected()
    	if err != nil {
    		fmt.Println("更新行 失败,err = ", err)
    		return
    	}
    	fmt.Printf("更新成功,更新行数: %d.\n", rows)
    }
    
    func main() {
    	err := initDB() // 初始化数据库
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    	} else {
    		fmt.Println("数据库go_db连接成功")
    	}
    	updateData()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    数据库go_db连接成功
    更新成功,更新行数: 1.
    
    [Done] exited with code=0 in 2.021 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数据库查看:

    在这里插入图片描述

    七 删除数据

    使用Exec方法

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

    实例演示:

    package main
    
    import (
    	"database/sql"
    	"fmt"
    
    	_ "github.com/go-sql-driver/mysql"
    )
    
    // 定义一个全局对象db
    var db *sql.DB
    
    // 定义一个初始化数据库的函数
    func initDB() (err error) {
    	dsn := "root:960690@tcp(127.0.0.1:3306)/go_db?charset=utf8mb4"
    
    	db, err = sql.Open("mysql", dsn)
    	if err != nil {
    		return err
    	}
    
    	err2 := db.Ping()
    	if err2 != nil {
    		return err2
    	}
    	return nil
    }
    
    func delData() {
    	sql := "delete from user_tb1 where id=?"
    	ret, err := db.Exec(sql, "2")
    	if err != nil {
    		fmt.Println("删除失败 err = ", err)
    		return
    	}
    
    	rows, err := ret.RowsAffected()
    	if err != nil {
    		fmt.Println("删除行失败 err = ", err)
    		return
    	}
    
    	fmt.Printf("删除成功,删除的行数: %d.\n", rows)
    }
    
    func main() {
    	err := initDB() // 初始化数据库
    	if err != nil {
    		fmt.Printf("err: %v\n", err)
    	} else {
    		fmt.Println("数据库go_db连接成功")
    	}
    	delData()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    运行结果:

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    数据库go_db连接成功
    删除成功,删除的行数: 1.
    
    [Done] exited with code=0 in 1.805 seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5

    数据库查看:

    在这里插入图片描述

  • 相关阅读:
    npm run dev和npm run serve两个命令的区别
    Python 自动化(十五)请求和响应
    半导体聚合物纳米颗粒,PSQPNs-DBCO点击化学, 二苯并环辛炔-PSQPNs
    Python 操作 CSV
    窗口函数-分组排序:row_number()、rank() 、dense_rank()、ntile()
    C#/VB.NET 如何在Excel中使用条件格式设置交替行颜色
    R语言ggplot2可视化:使用ggpubr包的ggline函数可视化分组折线图(点线图、line plot)、linetype参数指定不同分组线型不同
    【C语言】const 关键字
    c++ || mutable_explicit_volatile关键字
    go写webasmbly
  • 原文地址:https://blog.csdn.net/qq_39280718/article/details/126183914