1、mysql

Go语言中的database/sql包定义了对数据库的一系列的操作。database/sql/driver包定义了对应的被数据库实现的接口。这些接口会被sql包使用,但是Go语言没有提供任何官方的数据库驱动,所以我们需要导入第三方的数据库驱动。不过我们连接数据库之后对数据库操作的大部分代码都使用sql包。

安装驱动

# mysql驱动
go get github.com/go-sql-driver/mysql
# Mysql     github.com/go-sql-driver/mysql
# MyMysql   github.com/ziutek/mymysql/godrv
# Postgres  github.com/lib/pq
# SQLite3   github.com/mattn/go-sqlite3
# MsSql     github.com/denisenkom/go-mssqldb
# MsSql     github.com/lunny/godbc
# Oracle    github.com/mattn/go-oci8

连接数据库

package main

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

var Db *sql.DB

func init() {
	// 用户名:密码@tcp(ip:port)/databse
	url := "root:123456@tcp(127.0.0.1:3306)/test"
	var err error
	Db, err = sql.Open("mysql", url)
	if err != nil {
		fmt.Println(err)
		return
	}
    // 设置最大连接数
	Db.SetMaxOpenConns(25)
	// 设置最大空闲连接数
	Db.SetMaxIdleConns(25)
	// 设置每个链接的过期时间
	Db.SetConnMaxLifetime(5 * time.Minute)
}
func main() {

}

结果集

Result

新增、更新、删除时返回的结果集

type Result interface {
	// 返回数据库响应命令生成的整数。
    // 通常,当插入新行时,这将来自“自动递增”列。
    // 并非所有数据库都支持此功能,而且此类语句的语法也各不相同。
	LastInsertId() (int64, error)

	// 返回受更新、插入或删除影响的行数。
	// 并非每个数据库或数据库驱动程序都支持此功能。
	RowsAffected() (int64, error)
}

数据库操作

增删改

func (db *DB) Exec(query string, args ...interface{}) (Result, error)
uuid := uuid.New()

// 增
insertResult, err := Db.Exec("insert into student (obj_id,name,age) values(?,?,?)", uuid.String(), "james", 21)
if err != nil {
    fmt.Println(err)
}
fmt.Println(insertResult.LastInsertId())
fmt.Println(insertResult.RowsAffected())

// 删
deleteResult, err := Db.Exec("delete from student where obj_id=?", "4bd928b0-ed8d-4bb7-8c23-7689206c48ca")
if err != nil {
    fmt.Println(err)
}
fmt.Println(deleteResult.LastInsertId())
fmt.Println(deleteResult.RowsAffected())

// 改
updateResult, err := Db.Exec("update student set age=? where obj_id=?", 55, "719b70cf-0935-46de-92f7-77c3df2073a0")
if err != nil {
    fmt.Println(err)
}
fmt.Println(updateResult.RowsAffected())

查询

// 查多个
func (db *DB) Query(query string, args ...any) (*Rows, error)
// 查单个
func (db *DB) QueryRow(query string, args ...any) *Row 

查单个

row := Db.QueryRow("select * from student where obj_id=?", "719b70cf-0935-46de-92f7-77c3df2073a0")
if row.Err() != nil {
    fmt.Println(row.Err())
}
var objId string
var name string
var age int
row.Scan(&objId, &name, &age)
fmt.Println(objId, name, age)

查多个

rows, err := Db.Query("select * from student")
if err != nil {
    fmt.Println(err)
}
stus := []map[string]any{}
for rows.Next() {
    var objId, name string
    var age int
    rows.Scan(&objId, &name, &age)
    stu := map[string]any{
        "objId": objId,
        "name":  name,
        "age":   age,
    }
    stus = append(stus, stu)
}
fmt.Println(stus)

预编译

类似与java原生jdbc的预编译,可以防止sql注入

func (db *DB) Prepare(query string) (*Stmt, error)
// 编译sql
stmt, err := Db.Prepare("insert into student (obj_id,name,age) values(?,?,?)")
if err != nil {
    fmt.Println(err)
}
//传参并执行
insertResult, err := stmt.Exec("1234", "lucy", 18)
if err != nil {
    fmt.Println(err)
}
fmt.Println(insertResult.LastInsertId())
fmt.Println(insertResult.RowsAffected())

事务

// 开启事务
tx, err = Db.Beginx()
if err != nil {
    fmt.Println(err)
    return
}
tx.MustExec("update student set name=?,age=? where obj_id=?", "tom", 25, "a1fc54ae-7206-11ed-867c-00ffcaea37ee")
tx.MustExec("update student set name=?,age=? where obj_id=?", "tom", 25, "a1fc54ae-7206-11ed-867c-00ffcaea37ee")
// 提交事务
err = tx.Commit()
if err != nil {
    fmt.Println(err)
    return
}