昨天发布了mysql的安装和一些预备知识,还没有涉及到代码,今天开始深入探讨如何在 Golang 中实现基本的 MySQL 数据库操作,包括如何连接数据库、执行 SQL 语句,以及如何管理事务。通过代码示例和详细讲解,相信各位优秀的开发伙伴能快速掌握这些基础技能。

1 连接数据库

在 Golang 中,常用的 MySQL 驱动是 `github.com/go-sql-driver/mysql`。该驱动提供了高效的数据库连接和操作接口。

首先,安装 MySQL 驱动:

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

数据库连接示例

以下代码展示了如何使用 sql.Open 和 db.Ping 方法连接 MySQL 数据库。

package main

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

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

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

	// 打开数据库连接
	db, err := sql.Open("mysql", dsn)

	if err != nil { // 如果连接失败,则退出程序
		log.Fatalf("数据库连接失败: %v\n", err)
	}

	defer db.Close() // 在函数结束时关闭数据库连接

	// 测试数据库连接
	err = db.Ping()

	if err != nil { // 如果连接失败,则退出程序
		log.Fatalf("无法连接到数据库: %v\n", err)
	}
	fmt.Println("成功连接到数据库")
}

注意

  1. DSN 格式:确保提供正确的用户名、密码、地址和数据库名称。
  2. 连接池管理:sql.Open 不会真正打开连接,而是为连接池创建一个句柄。
  3. 连接关闭:始终在函数结束前调用 defer db.Close() 释放资源。

2 执行 SQL 语句

Golang 提供了 Exec、Query 和 QueryRow 等方法,用于执行 SQL 语句和查询操作。

package main

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

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

// 插入数据
func insertData(db *sql.DB) { // 定义一个函数,用于插入数据

	sql := "INSERT INTO users (name, age) VALUES (?, ?)" // 定义SQL语句

	result, err := db.Exec(sql, "风云", 35) // 执行SQL语句,并获取结果

	if err != nil { // 如果插入失败,则退出程序
		log.Fatalf("插入数据失败: %v\n", err)
	}

	id, _ := result.LastInsertId() // 获取插入数据的ID

	fmt.Printf("插入成功,ID: %d\n", id)
}

// 查询数据
func queryData(db *sql.DB) { // 定义一个函数,用于查询数据

	sql := "SELECT id, name, age FROM users" // 定义SQL语句

	rows, err := db.Query(sql)

	if err != nil { // 如果查询失败,则退出程序
		log.Fatalf("查询数据失败: %v\n", err)
	}

	defer rows.Close() // 关闭结果集

	for rows.Next() {
		var id int

		var name string

		var age int

		if err := rows.Scan(&id, &name, &age); err != nil {
			log.Fatalf("读取行数据失败: %v\n", err)
		}

		fmt.Printf("ID: %d, Name: %s, Age: %d\n", id, name, age)
	}
}

// 更新数据
func updateData(db *sql.DB) { // 定义一个函数,用于更新数据

	sql := "UPDATE users SET age = ? WHERE name = ?"

	result, err := db.Exec(sql, 30, "Alice") // 执行SQL语句,并获取结果

	if err != nil { // 如果更新失败,则退出程序
		log.Fatalf("更新数据失败: %v\n", err)
	}

	rowsAffected, _ := result.RowsAffected()

	fmt.Printf("更新成功,影响行数: %d\n", rowsAffected)

}

// 删除数据
func deleteData(db *sql.DB) { // 定义一个函数,用于删除数据

	sql := "DELETE FROM users WHERE name = ?"

	result, err := db.Exec(sql, "Alice") // 执行SQL语句,并获取结果

	if err != nil { // 如果删除失败,则退出程序
		log.Fatalf("删除数据失败: %v\n", err)
	}

	rowsAffected, _ := result.RowsAffected()

	fmt.Printf("删除成功,影响行数: %d\n", rowsAffected)
}

func main() {
	// 数据库连接信息
	dsn := "netwindcloud:netwindcloud123@tcp(127.0.0.1:3306)/netwindcloud"

	// 打开数据库连接
	db, err := sql.Open("mysql", dsn)

	if err != nil { // 如果连接失败,则退出程序
		log.Fatalf("数据库连接失败: %v\n", err)
	}

	defer db.Close() // 在函数结束时关闭数据库连接

	// 测试数据库连接
	err = db.Ping()

	if err != nil { // 如果连接失败,则退出程序
		log.Fatalf("无法连接到数据库: %v\n", err)
	}
	fmt.Println("成功连接到数据库")

	// 调用 insertData 函数
	// insertData(db)

	queryData(db)  // 调用 queryData 函数
	updateData(db) // 调用 updateData 函数
	// deleteData(db) // 调用 deleteData 函数
}

3 事务操作

事务是一组操作的集合,这些操作要么全部成功,要么全部回滚。

事务基本用法

使用 Begin 开启事务,Commit 提交事务,Rollback 回滚事务。

func transactionExample(db *sql.DB) { // 定义一个函数,用于执行事务

	tx, err := db.Begin()

	if err != nil { // 如果事务开启失败,则退出程序
		log.Fatalf("事务开启失败: %v\n", err)
	}

	// 执行第一条语句
	_, err = tx.Exec("UPDATE accounts SET balance = balance - 100 WHERE id = ?", 1)

	if err != nil { // 如果更新失败,则回滚事务
		tx.Rollback() // 回滚事务

		log.Fatalf("更新账户余额失败: %v\n", err)
	}

	// 执行第二条语句
	_, err = tx.Exec("UPDATE accounts SET balance = balance + 100 WHERE id = ?", 2)

	if err != nil { // 如果更新失败,则回滚事务
		tx.Rollback() // 回滚事务

		log.Fatalf("更新账户余额失败: %v\n", err)
	}

	// 提交事务

	err = tx.Commit()

	if err != nil {
		log.Fatalf("提交事务失败: %v\n", err)
	}

	fmt.Println("事务执行成功")
}

注意事项

  1. 异常处理:在事务中,任何错误都需要立即回滚。
  2. 事务嵌套:Golang 不支持事务嵌套,需要手动管理逻辑。