0%

Go操作MySQL数据库

Go语言中的database/sql包提供了保证SQL或类SQL数据库的泛用接口,并不提供具体的数据库驱动。使用database/sql包时必须注入(至少)一个数据库驱动。

我们常用的数据库基本上都有完整的第三方实现。例如:MySQL驱动

基本的数据库操作接口

下面是操作mysql数据库的基本接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* open函数打开一个指定的数据库,数据库的类型使用driverName参数字段表示的数据库类型,
dataSourceName参数字段则是指定的数据库账户密码地址等信息 */
func Open(driverName, dataSourceName string) (*DB, error)

/* QueryRow函数执行一次查询,并且返回一行数据 */
func (db *DB)QueryRow(query string, args...interface{}) *Row

/* Query函数执行一次查询,返回多行数据结果,参数中args表示函数中的占位数 */
func (db *DB)Query(query string, args...interface{})(*Rows, error)

/* exec执行一次命令(包括删除、更新、插入等),返回的Result是已执行的sql命令的SQL命令的总结。
参数args表示query中的占位数 */
func (db *DB)Exec(query string, args...interface{})(Result, error)

/* Prepare函数会先将sql语句发送给sql数据库,返回一个已经准备好的句柄(准备好的状态)
用于后面的查询和命令,返回值可以同时执行多个查询和命令 */
func (db *DB)Prepare(query string)(*Stmt, error)

MySQL事务操作

事务: 事务是一个最小的不可再分的一个执行单位,主要是某些场景用来保证完整性。

在MySQL中只有使用了Innodb数据库引擎的数据库或者表才会支持事务操作。

1
2
3
4
5
6
/* 开始事务 */
func (db *DB)Begin()(*Tx, error)
/* 提交事务 */
func (tx *Tx)Commit()error
/* 回滚事务 */
func (tx *Tx)Rollback()error

Go操作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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package main

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

/* 定义查询结果集结构 */
type user struct {
id int
age int
name string
}

/* 初始化全部的数据库句柄 */
var db *sql.DB


/* 初始化数据库连接 */
func initDb() (err error) {
dsn := "root:yuan1121@tcp(127.0.0.1:3306)/lpyuan?charset=utf8mb4&parseTime=True"
db, err = sql.Open("mysql", dsn)
if err != nil {
fmt.Println("open mysql failed")
return err
}

/* 尝试与数据库连接 */
err = db.Ping()
if err != nil {
return err
}
return nil
}

/* 查询单行数据 */
func queryRowDemon() {
var u user
sqlstr := "select id, name, age from user where id =?"
err := db.QueryRow(sqlstr, 2).Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Println("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
}

/* 查询多行数据 */
func queryMultiRowDaemon() {
sqlstr := "select id, name, age from user where id > ?"
rows, err := db.Query(sqlstr, 0)
if err != nil {
fmt.Println("db.Query failed, err:", err)
return
}
defer rows.Close()
for rows.Next() {
var u user
err := rows.Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Println("Scan failed , err:", err)
return
}
fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
}
}

/* 插入数据 */
func insertRowDaemon() {
sqlstr := "insert into user(name, age) values (?, ?)"
ret, err := db.Exec(sqlstr, "张龙", 26)
if err != nil {
fmt.Println("Exec failed")
return
}
theId, err := ret.LastInsertId()
if err != nil {
fmt.Println("get last insterId is failed")
return
}
fmt.Printf("insert success, the id is %d", theId)
}

/* 删除数据操作 */
func deleteRowDemo() {
sqlStr := "delete from user where id = ?"
ret, err := db.Exec(sqlStr, 3)
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影响的行数
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return
}
fmt.Printf("delete success, affected rows:%d\n", n)
}

func prepareDemon() {
sqlstr := "insert into user(name, age) values(?, ?)"
stmt, err := db.Prepare(sqlstr)
if err != nil {
fmt.Println("Prepare sqlstr failed")
return
}
defer stmt.Close()
_, err = stmt.Query("马汉", 23)
if err != nil {
fmt.Println("stmt.Query failed")
return
}
_, err = stmt.Query("李白", 21)
if err != nil {
fmt.Println("stmt.Query failed ")
return
}

var m = map[string]int{
"赵虎":22,
"打算的撒":23,
"银行":24,
}
for k, v := range m {
stmt.Exec(k, v)
}
fmt.Println("insert success")
}

/* 提交事务操作 */
func transactionDemon(){
/* 开启事务 */
tx, err := db.Begin()
if err != nil{
if tx != nil{
tx.Rollback()
}
fmt.Println("begin trans failed, err:", err)
return
}
sqlstr1 := "Update user set age = 30 where id = ?"
ret1, err := tx.Exec(sqlstr1, 2)
if err != nil{
fmt.Println("Exec sql1 error, err:", err)
tx.Rollback()
return
}
affRows1, err := ret1.RowsAffected()
if err != nil{
tx.Rollback()
fmt.Println("RowsAffected failed")
return
}
sqlstr2 := "Update user set age=40 where id=?"
ret2, err := tx.Exec(sqlstr2, 3)
if err != nil{
tx.Rollback()
fmt.Println("exec sqlstr2 failed, err:", err)
return
}
affRows2, err := ret2.RowsAffected()
if err != nil{
tx.Rollback()
fmt.Println("RowsAffected failed, err:", err)
return
}
fmt.Printf("affRows1:%d affRows2:%d\n", affRows1, affRows2)
if affRows1 == 1 && affRows2 == 1{
fmt.Println("事务提交了。。。")
tx.Commit()
}else{
tx.Rollback()
fmt.Println("事务回滚了~")
}
fmt.Println("exec trans success")
}


/* 主函数main */
func main() {
err := initDb()
if err != nil {
fmt.Println("initDB error!")
return
}
fmt.Println("连接数据库成功")
fmt.Println("单行查询:")
queryRowDemon()
fmt.Println("多行查询:")
queryMultiRowDaemon()
transactionDemon()

}

reference

[1] https://www.liwenzhou.com/posts/Go/go_mysql/

小主,路过打个赏再走呗~