创建一个go_db数据库
create database go_db;
 
打开数据库
use go_db;
 
创建表
 create table user_tb1(
     id integer primary key auto_increment,
     username varchar(20),
     password varchar(20)
 );
 
添加模拟数据
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");
 
详细过程:
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>
 
二 安装配置mysql驱动 
安装驱动
go get -u github.com/go-sql-driver/mysql
 
初始化模块
go mod init m
 
执行go mod tidy
go mod tidy
 
导入驱动(官方示例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)
}
 
三 获得数据库连接 
3.1 导入包
import (
	"database/sql"
	"time"
	_ "github.com/go-sql-driver/mysql"
)
 
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)
}
 
运行结果:
[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
 
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)
}
 
运行结果:
[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
 
四 插入数据 
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 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()
}
 
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
数据库go_db连接成功
插入成功,id是: 4.
[Done] exited with code=0 in 1.657 seconds
 
数据库查看:

实例演示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")
}
 
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
数据库go_db连接成功
插入成功,id是: 6.
[Done] exited with code=0 in 1.673 seconds
 
数据库查看:

5.1 单行查询
db.QueryRow() 
QueryRow总是返回非nil的值,知道返回值的Scan方法被调用时,才会返回延迟的错误。
func (db *DB) QueryRow(query string, args ...any) *Row 
 
先定义一个结构体:
type user struct {
	id       int
	username string
	password string
}
 
实例演示:
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()
}
 
运行结果:
[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
 
5.2 多行查询
db.Query() 
参数args表示query中的占位参数。
func (db *DB) Query(query string, args ...any) (*Rows, error)
 
实例演示:
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()
}
 
运行结果:
[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
 
六 更新数据 
Exec 
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
 
实例演示:
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()
}
 
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
数据库go_db连接成功
更新成功,更新行数: 1.
[Done] exited with code=0 in 2.021 seconds
 
数据库查看:

Exec 
func (db *DB) Exec(query string, args ...interface{}) (Result, error)
 
实例演示:
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()
}
 
运行结果:
[Running] go run "e:\golang开发学习\go_pro\test.go"
数据库go_db连接成功
删除成功,删除的行数: 1.
[Done] exited with code=0 in 1.805 seconds
 
数据库查看:
