Go 连接 MySql 数据库

驱动

为了Go语言可以提前定义操作一个数据库的所有行为(接口)和数据(结构体)的规范,这些定义在database/sql下。

MySQL驱动

go-sql-driver/mysql库是Go语言官方推荐的MySQL驱动库,可以很方便地实现对MySQL数据库的连接和操作。

安装mysql Go驱动

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

导入

1
import _ "github.com/go-sql-driver/mysql" // 当导入带有空白标识符前缀 _ 的包时,将调用包的 init 函数。该函数注册驱动程序

注册驱动

1
2
3
4
// github.com/go-sql-driver/mysql/mysql/driver.go 代码中有注册驱动
func init() { // 83行
sql.Register("mysql", &MySQLDriver{})
}

连接数据库

DSN例子 https://github.com/go-sql-driver/mysql#examples

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]

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
package main

import (
"database/sql"
"log"
"time"
_ "github.com/go-sql-driver/mysql" // 1 驱动安装和导入
)

var db *sql.DB

func init() {
// 2 连接数据库
var err error
db, err = sql.Open("mysql", "root:123456@tcp(localhost:3306)/test") // 不要使用:=
defer db.Close()
if err != nil {
log.Fatal(err)
}

// 查看README.md https://github.com/go-sql-driver/mysql#usage
db.SetConnMaxLifetime(time.Second * 30) // 超时时间
db.SetMaxOpenConns(0) // 设置最大连接数,默认为0表示不限制
db.SetMaxIdleConns(10) // 设置空闲连接数
}

db类型是*sql.DB,是一个操作数据库的句柄,底层是一个多协程安全的连接池。

操作数据库

获取mysql版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 获取mysql版本
func showMysqlVersion() {
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4")
db.Ping()
defer db.Close()

if err != nil {
fmt.Println("数据库连接失败!")
log.Fatalln(err)
}

var version string

err2 := db.QueryRow("SELECT VERSION()").Scan(&version)

if err2 != nil {
log.Fatal(err2)
}

fmt.Println(version)
}

创建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 创建表
func createTable() {
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/Test")
db.Ping()
defer db.Close()

if err != nil {
fmt.Println("connect DB error !")
log.Fatalln(err)
}

_, err2 := db.Exec("CREATE TABLE user(id INT NOT NULL , name VARCHAR(20), PRIMARY KEY(ID));")
if err2 != nil {
log.Fatal(err2)
}

fmt.Println("successfully create table")
}

插入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 插入数据
func insertItem() {
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/Test?charset=utf8mb4")
db.Ping()
defer db.Close()

if err != nil {
fmt.Println("connect DB error !")
log.Fatalln(err)
}

_, err2 := db.Query("INSERT INTO user VALUES(1, 'zhangsan')")
if err2 != nil {
log.Fatal(err2)
}

fmt.Println("successfully insert item")
}

删除数据

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
// 删除数据
func deleteItem() {
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/Test?charset=utf8mb4")
db.Ping()
defer db.Close()

if err != nil {
fmt.Println("connect DB error !")
log.Fatalln(err)
}

sql := "DELETE FROM user WHERE id = 1"
res, err2 := db.Exec(sql)

if err2 != nil {
panic(err2.Error())
}

affectedRows, err := res.RowsAffected()

if err != nil {
log.Fatal(err)
}

fmt.Printf("delete item success, statement affected %d rows\n", affectedRows)
}

修改数据

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
// 修改数据
func alterItem() {
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/Test?charset=utf8mb4")
db.Ping()
defer db.Close()

if err != nil {
fmt.Println("connect DB error !")
log.Fatalln(err)
}

sql := "update user set name = ? WHERE id = ?"
res, err2 := db.Exec(sql, "lisi", 1)

if err2 != nil {
panic(err2.Error())
}

affectedRows, err := res.RowsAffected()

if err != nil {
log.Fatal(err)
}

fmt.Printf("alter item success, statement affected %d rows\n", affectedRows)
}

查询数据

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
66
67
68
69
70
71
72
73
74
75
76
// 查询数据
package main

import (
"database/sql"
"fmt"
"log"
"time"

_ "github.com/go-sql-driver/mysql" // 1 驱动安装和导入
)

var db *sql.DB

func init() {
// 2 连接数据库
var err error
db, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4") // 不要使用:=
if err != nil {
log.Fatal(err)
}

// 查看README.md https://github.com/go-sql-driver/mysql#usage
db.SetConnMaxLifetime(time.Second * 30) // 超时时间
db.SetMaxOpenConns(0) // 设置最大连接数,默认为0表示不限制
db.SetMaxIdleConns(10) // 设置空闲连接数
}

type Emp struct { // 和字段对应的变量或结构体定义,最好和数据库中字段顺序对应
emp_no int
birth_date string
first_name string
last_name string
gender int16
hire_date string
}

func main() {
// 3 操作
// 预编译
stmt, err := db.Prepare("select * from employees where emp_no > ?")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
// 批量查询
rows, err := stmt.Query(10018)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
emp := Emp{}
for rows.Next() {
err = rows.Scan(&emp.emp_no, &emp.birth_date, &emp.first_name,
&emp.last_name, &emp.gender, &emp.hire_date) // 取字段
if err != nil {
log.Fatal(err)
}
fmt.Println(emp)
fmt.Printf("%T %[1]v\n", emp.birth_date)
t, err := time.Parse("2006-01-02", emp.birth_date) // 时间解析
if err != nil {
log.Fatal(err)
}
fmt.Printf("%T %[1]v\n", t)
}
fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~")
// 单行查询
row := db.QueryRow("select * from employees where emp_no = ?", 10010)
err = row.Scan(&emp.emp_no, &emp.birth_date, &emp.first_name,
&emp.last_name, &emp.gender, &emp.hire_date) // 取字段
if err != nil {
log.Fatal(err)
}
fmt.Println(emp)
}

删除表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 删除表
func dropTable() {
db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/Test")
db.Ping()
defer db.Close()

if err != nil {
fmt.Println("connect DB error !")
log.Fatalln(err)
}

_, err2 := db.Exec("DROP TABLE user;")
if err2 != nil {
log.Fatal(err2)
}

fmt.Println("successfully drop table")
}
-------------本文结束感谢您的阅读-------------