目录

一、简介

二、数据结构

三、菜鸟实战

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

二、数据结构

数据库操作主要包括:

  1. 连接数据库
  2. 插入数据
  3. 查询单条数据
  4. 查询多条数据
  5. 更新数据
  6. 删除数据

三、菜鸟实战

实战场景:用 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

 菜鸟实战,持续学习!