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() {
}
新增、更新、删除时返回的结果集
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
}