一个计算机技术爱好者与学习者

0%

好好学Golang:Golang操作MySQL

1. 前言

在实际的开发中,操作数据库是必不可少的环节。
Go语言通过标准库database/sql以及相对应的数据库驱动第三方库,让数据库操作变得简明而强大。
本文中,我们将会学习安装MySQL数据库驱动,以及如何进行增删查改(CRUD)操作。

2. 安装MySQL数据库驱动

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

3. 打开数据库连接

使用sql.Open函数和 MySQL DSN 打开一个数据库连接。

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

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

_ "github.com/go-sql-driver/mysql"
)

func main() {
// 数据库连接信息
dsn := "root:mysql123@tcp(192.168.50.133:3306)/mysql"

// Open函数会开启一个数据库连接,注意此时并不会立即校验用户名和密码的正确性
// 它仅仅是初始化一个连接的对象
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatalf("Error on initializing database connection: %s", err.Error())
}

// 可以使用Ping方法来校验用户名和密码的正确性
err = db.Ping()
if err != nil {
log.Fatalf("Error on opening database connection: %s", err.Error())
}
defer db.Close()

// 查询示例
query := `SELECT version();` // 一个简单的查询,获取MySQL版本信息
var version string
err = db.QueryRow(query).Scan(&version)
if err != nil {
log.Fatalf("Query failed: %s", err.Error())
}

fmt.Printf("Connected to MySQL database successfully! MySQL version: %s\n", version)
}

在写我们的MySQL连接字符串(DSN,即Data Source Name)时,确保我们指定了正确的用户名、密码、地址、端口和数据库名称。

注意事项

  • 代码中_ "github.com/go-sql-driver/mysql"的import表明引入了mysql驱动,但是并没有直接使用它,_的用法在Go中用来进行仅初始化该包而不实际使用包中任何函数、变量等。
  • 需要具体根据我们的MySQL服务器的用户名(username), 密码 (password), 服务器地址 (127.0.0.1), 端口 (3306), 和数据库名(dbname)来编辑DSN。
  • db.Ping()是用来检查与数据库的连接是否仍然有效,或者在初次尝试时,确认能够建立连接。
  • 最后,使用defer db.Close()来确保数据库连接被正确关闭,这是避免内存泄漏的一个重要习惯。defer关键字会安排随后的函数调用在函数返回时执行。
  • 该示例中只执行了一个简单的SELECT查询来获取MySQL的版本信息,并将其打印到标准输出。在实际的应用程序中,我们可能需要执行更复杂的SQL查询和其他数据库操作。
  • 在生产环境中,应该避免明文存储敏感信息如数据库的用户名和密码,可以考虑使用环境变量或加密存储这些信息。

3.1. 创建一个测试数据库和表

1
2
3
4
5
6
7
8
9
10
create database test default character set utf8 collate utf8_general_ci;

use test;

create table if not exists `user` (
`id` int(8) not null auto_increment,
`name` varchar(32) not null,
`age` int(4) not null default 0,
primary key (id)
) engine=innodb default charset=utf8;

4. 增删查改操作

4.1. 创建(Create)

创建记录通常使用INSERT语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func create(db *sql.DB) {
query := `INSERT INTO user(name, age) VALUES(?, ?)`
result, err := db.Exec(query, "John Doe", 28)
if err != nil {
log.Fatal(err)
}

id, err := result.LastInsertId()
if err != nil {
log.Fatal(err)
}

fmt.Printf("New record ID: %d\n", id)
}

4.2. 读取(Read)

读取记录可以使用SELECT语句。查询单条结果可以使用QueryRow,查询多条结果可以使用Query

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
func read(db *sql.DB) {
query := `SELECT id, name, age FROM user WHERE age > ?`
rows, err := db.Query(query, 18)
if err != nil {
log.Fatal(err)
}
defer rows.Close()

for rows.Next() {
var id int
var name string
var age int
err = rows.Scan(&id, &name, &age)
if err != nil {
log.Fatal(err)
}
fmt.Printf("ID: %d, Name: %s, Age: %d\n", id, name, age)
}

// Check for errors from iterating over rows.
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}

4.3. 更新(Update)

更新记录通常使用UPDATE语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func update(db *sql.DB) {
query := `UPDATE user SET age = ? WHERE name = ?`
result, err := db.Exec(query, 30, "John Doe")
if err != nil {
log.Fatal(err)
}

count, err := result.RowsAffected()
if err != nil {
log.Fatal(err)
}

fmt.Printf("Affected rows: %d\n", count)
}

4.4. 删除(Delete)

删除记录通常使用DELETE语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func delete(db *sql.DB) {
query := `DELETE FROM user WHERE name = ?`
result, err := db.Exec(query, "John Doe")
if err != nil {
log.Fatal(err)
}

count, err := result.RowsAffected()
if err != nil {
log.Fatal(err)
}

fmt.Printf("Removed rows: %d\n", count)
}

4.5. 完整示例

以下是综合上述功能的一个完整示例:

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

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

_ "github.com/go-sql-driver/mysql"
)

func main() {
// 数据库连接信息
dsn := "root:mysql123@tcp(192.168.50.133:3306)/test"

// Open函数会开启一个数据库连接,注意此时并不会立即校验用户名和密码的正确性
// 它仅仅是初始化一个连接的对象
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatalf("Error on initializing database connection: %s", err.Error())
}

// 可以使用Ping方法来校验用户名和密码的正确性
err = db.Ping()
if err != nil {
log.Fatalf("Error on opening database connection: %s", err.Error())
}
defer db.Close()

create(db)
read(db)
update(db)
read(db)
delete(db)
}

// create function implementation ...
// read function implementation ...
// update function implementation ...
// delete function implementation ...

5. 注意事项

  • 在任何数据库操作之后,如果出现错误,请确保进行错误处理(if err != nil)。
  • 当使用rows进行查询时,我们必须通过rows.Close()来关闭rows,防止资源泄露。
  • 使用defer来确保数据库连接被关闭。
  • 在生产环境中,考虑使用连接池管理数据库连接,Go的database/sql包已经默认实现了连接池。
  • 在实际场景中,多考虑使用事务管理(db.Begin()),以保证数据的一致性。
  • 确保处理sql.ErrNoRows错误,当期望的行不存在时会返回此错误。

按照上文中的办法,即可完成在Go中对MySQL数据库进行基础的增删查改操作。在更高级的应用中,我们可能会涉及到更加复杂的事务、加锁策略和性能优化问题。

  • 本文作者: 好好学习的郝
  • 原文链接: https://www.voidking.com/dev-golang-mysql/
  • 版权声明: 本文采用 BY-NC-SA 许可协议,转载请注明出处!源站会即时更新知识点并修正错误,欢迎访问~
  • 微信公众号同步更新,欢迎关注~