目录
一、简介
二、数据结构
三、菜鸟实战
1、创建 g012.go
2、编译和运行
3、运行结果
一、简介
目前流行的网站构架方式是 LAMP,其中的 M 即 MySQL。作为数据库,MySQL 以免费、开源、使用方便为优势成为了很多 Web 开发的后端数据库存储引擎,MySQL 也是目前开发中最常见的关系型数据库。
Go 中支持 MySQL 的驱动目前比较多,常用的有如下几种:
- github.com/go-sql-driver/mysql
- github.com/ziutek/mymysql
- github.com/Philio/GoMySQL
接下来的例子主要以 github.com/go-sql-driver/mysql 实战,主要理由:
- 比较新,维护的比较好
- 完全支持 database/sql 接口
- 支持 keepalive
二、数据结构
数据库操作主要包括:
- 连接数据库
- 插入数据
- 查询单条数据
- 查询多条数据
- 更新数据
- 删除数据
三、菜鸟实战
实战场景:用 Go 实现数据库的基本操作
马上安排!
1、创建 g012.go
/*
* @Author: 菜鸟实战
* @FilePath: /go110/go-012/g012.go
* @Description: Go 数据库基本操作
*/
package main
import (
"database/sql"
"fmt"
"runtime"
_ "github.com/go-sql-driver/mysql"
)
/**
// 创建 user 表
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
`age` int NOT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户信息表'
**/
// 全局对象 db
var db *sql.DB
// 定义一个 user 结构体接收数据:
type user struct {
id int
age int
name string
}
// 始化数据库的函数
func initDB() (err error) {
// 构建连接的 dsn 格式是:"用户名:密码@tcp(IP:端口)/数据库?charset=utf8"
dsn := "user:password@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True"
// 给全局变量赋值, 注意这里不要使用 :=
db, err = sql.Open("mysql", dsn)
if err != nil {
fmt.Println("初始化数据库失败")
return err
}
// 校验dsn是否正确
fmt.Println("尝试与数据库建立连接...")
err = db.Ping()
if err != nil {
fmt.Println("连接失败")
return err
}
fmt.Println("连接成功")
db.SetMaxOpenConns(2000) // 设置最大打开连接数
db.SetMaxIdleConns(10) // 设置最大空闲连接数
return nil
}
// 插入数据
func insertRow(name string, age int) int64 {
sqlStr := "INSERT INTO user(name, age) VALUES (?,?)"
ret, err := db.Exec(sqlStr, name, age)
if err != nil {
fmt.Printf("插入失败, err: %v\n", err)
return 0
}
// 新插入数据的 id
insertId, err := ret.LastInsertId()
if err != nil {
fmt.Printf("获取新插入数据的 ID 失败, err:%v\n", err)
return 0
}
fmt.Printf("插入成功, ID 为 %d.\n", insertId)
return insertId
}
// 查询单条数据记录
func queryRow(rowId int64) {
sqlStr := "SELECT id, name, age FROM user WHERE id = ?"
var u user
// 确保 QueryRow 之后调用 Scan 方法,释放持有的数据库链接
err := db.QueryRow(sqlStr, rowId).Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("未找到记录, 查询失败, err: %v\n", err)
return
}
fmt.Printf("查询数据成功, id: %d name: %s age: %d \n", u.id, u.name, u.age)
}
// 更新数据
func updateRow(rowId int64, newAge int) {
sqlStr := "UPDATE user SET age=? WHERE id = ?"
ret, err := db.Exec(sqlStr, newAge, rowId)
if err != nil {
fmt.Printf("更新失败 , err:%v\n", err)
return
}
// 操作影响的行数
n, err := ret.RowsAffected()
if err != nil {
fmt.Printf("获取影响函数失败, err: %v\n", err)
return
}
fmt.Printf("更新成功, 影响行数为: %d\n", n)
}
// 删除数据
func deleteRow(rowId int64) {
sqlStr := "DELETE FROM user WHERE id = ?"
ret, err := db.Exec(sqlStr, rowId)
if err != nil {
fmt.Printf("删除失败, err: %v\n", err)
return
}
n, err := ret.RowsAffected() // 操作影响的行数
if err != nil {
fmt.Printf("获取影响函数失败, err: %v\n", err)
return
}
fmt.Printf("删除成功, 影响行数为: %d\n", n)
}
// 查询多行
func queryMultiRow() {
sqlStr := "SELECT id, name, age FROM user WHERE id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {
fmt.Printf("查询失败, err:%v\n", err)
return
}
// 重要:关闭 rows, 释放持有的数据库链接
defer rows.Close()
// 循环读取结果集中的数据
for rows.Next() {
var u user
err := rows.Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("查询多行数据失败, err:%v\n", err)
return
}
fmt.Printf("当前数据 id: %d name: %s age: %d\n", u.id, u.name, u.age)
}
}
func main() {
// 使用内置函数打印
println("Hello", "菜鸟实战")
// 初始化数据库
initDB()
// 插入数据
var id1 = insertRow("唐遇春", 17)
var id2 = insertRow("冯显", 38)
var id3 = insertRow("花千里", 20)
// 查询多行数据
queryMultiRow()
// 更新数据
updateRow(id2, 35)
// 查询单行数据
queryRow(id2)
// 删除数据
deleteRow(id1)
// 查询多行数据
queryMultiRow()
queryRow(id3)
// 当前版本
fmt.Printf("版本: %s \n", runtime.Version())
}
2、编译和运行
# 1、生成模块依赖
go mod init g012
# 2、编译
go build g012.go
# 3、编译后的目录结构└── go-012
├── g012
├── g012.go
└── go.mod
# 4、运行
go run g012
3、运行结果
Hello 菜鸟实战
尝试与数据库建立连接...
连接成功
插入成功, ID 为 1.
插入成功, ID 为 2.
插入成功, ID 为 3.
当前数据 id: 1 name: 唐遇春 age: 17
当前数据 id: 2 name: 冯显 age: 38
当前数据 id: 3 name: 花千里 age: 20
更新成功, 影响行数为: 1
查询数据成功, id: 2 name: 冯显 age: 35
删除成功, 影响行数为: 1
当前数据 id: 2 name: 冯显 age: 35
当前数据 id: 3 name: 花千里 age: 20
查询数据成功, id: 3 name: 花千里 age: 20
版本: go1.17.10
菜鸟实战,持续学习!