获取数据库驱动
go get -u github.com/go-sql-driver/mysql
如果你遇到下面的错误,
键入这行命令即可(亲测有效)
go env -w GO111MODULE=auto
GO111MODULE 是一个控制 Go 模块机制行为的环境变量。当 GO111MODULE 的值为 auto 时,Go 命令会自动判断是否在模块模式下运行。如果当前目录下存在一个 go.mod 文件,则认为在模块模式下运行;否则认为在传统的 GOPATH 模式下运行。
在模块模式下,Go 会自动下载并管理依赖项,并且可以使用更加灵活的版本控制方式。而在 GOPATH 模式下,则需要手动下载并管理依赖项,并且版本控制方式相对固定。
如果不想手动设置 GO111MODULE 环境变量,并希望让 Go 命令自动判断模式,可以使用 go env -w GO111MODULE=auto 命令来设置。这个命令会将 GO111MODULE 环境变量设置为 auto,从而让 Go 命令自动判断模式。
连接初始化
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql" // 匿名导入 自动执行 init()
"net/url"
"time"
)
// 声明一个db
var db *sql.DB
func initMysql() (err error) {
// 东八区,允许解析时间字段
// 如果你有datetime 类型的字段,方便后面解析
// 后面的 parseTime 必须要有,用法如下:
dsn := "root:123456@tcp(127.0.0.1:3306)/你的库名?charset=utf8&loc=" + url.QueryEscape("Asia/Shanghai") + "&parseTime=true"
// 只对格式进行校验,并不会真正连接数据库
db, err = sql.Open("mysql", dsn)
if err != nil {
return err
}
// Ping 验证与数据库的连接是否仍处于活动状态,并在必要时建立连接。
err = db.Ping()
if err != nil {
fmt.Printf("connect to db failed, err: %v\n", err)
return err
}
// 数值需要根据业务具体情况来确定
// 设置可以重用连接的最长时间
db.SetConnMaxLifetime(time.Second * 60)
// 设置连接可能处于空闲状态的最长时间
db.SetConnMaxIdleTime(time.Second * 30)
// 设置与数据库的最大打开连接数
db.SetMaxOpenConns(200)
// 设置空闲连接池中的最大连接数
db.SetMaxIdleConns(10)
return nil
}
func main() {
if err := initMysql(); err != nil {
fmt.Printf("connect to db failed, err: %v\n", err)
}
// 检查完错误之后执行,确保 db 不为 nil
// Close() 用来释放数据库连接相关的资源
defer func(db *sql.DB) {
err := db.Close()
if err != nil {
panic(err)
}
}(db)
fmt.Println(">>>>>>数据库格式正确,接着往下走")
}
运行结果
CURD
查询数据
// 定义一个结构体,首先你得去数据创建这张Team表
type Team struct {
TeamId int
TeamName string
TeamDesc string
CreateTime time.Time
}
// 查询单行数据
func queryDemo(id int) (Team, error) {
sqlStr := "select teamId, teamName, teamDesc from team where teamId = ? "
var team Team
// QueryRow 执行预期最多返回一行的查询。
// QueryRow 始终返回一个非 nil 值。错误将延迟到调用 row 的 Scan 方法。
// Scan 将匹配行中的列复制到 dest 指向的值中
// 如果多行与查询匹配,Scan 将使用第一行并丢弃其余行。
// 如果没有与查询匹配的行,Scan 将返回 ErrNoRows。
// QueryRow 之后要调用 Scan 方法,否则数据库连接不会被释放
// Scan 源码:defer r.rows.Close()
err := db.QueryRow(sqlStr, id).Scan(&team.TeamId, &team.TeamName, &team.TeamDesc)
if err != nil {
fmt.Printf("scan failed ,err: ->%v\n", err)
return team, err
}
return team, nil
}
func main() {
if err := initMysql(); err != nil {
fmt.Printf("connect to db failed, err: %v\n", err)
}
// 检查完错误之后执行,确保 db 不为 nil
// Close() 用来释放数据库连接相关的资源
defer func(db *sql.DB) {
err := db.Close()
if err != nil {
panic(err)
}
}(db)
fmt.Println(">>>>>>数据库格式正确,接着往下走")
fmt.Println("===========================")
//>>>>>>>>>>>>> 查单行
team, err := queryDemo(33)
if err != nil {
fmt.Printf("query row failed, err: %v", err)
}
fmt.Printf("id: %d name: %s desc: %s\n", team.TeamId, team.TeamName, team.TeamDesc)
}
结果
// 查询多条数据
func queryMultiRowDemo(id int) {
sqlStr := "select teamId, teamName, teamDesc , createTime from team where teamId > ? "
rows, err := db.Query(sqlStr, id)
if err != nil {
fmt.Printf("query failed, err: %v\n", err)
return
}
// 关闭 rows 释放持有的数据库链接
// Close 关闭行,防止进一步枚举。
// 如果调用 Next 并返回 false 并且没有其他结果集,
// 则行将自动关闭,检查 Err. 的结果就足够了。 关闭是幂等的,不会影响 Err 的结果。
// 因为不能保证 for rows.Next() 一定可以执行完,有可能会 panic 或其他情况,
// 故需要在此 defer 关闭连接
defer rows.Close()
// 循环读取结果集中的数据
// Next 准备下一个结果行,以便使用 Scan 方法读取。
// 成功时返回 true,如果没有下一个结果行或在准备时发生错误,则返回 false。
for rows.Next() {
var team Team
err := rows.Scan(&team.TeamId, &team.TeamName, &team.TeamDesc, &team.CreateTime)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return
}
// 将Time类型的时间格式化成`int64`类型(timestamp)
//createtime := team.CreateTime.Unix()
// 将Time类型的时间格式化成`string`类型(Y-m-d H:i:s)
/*
一个格式化字符串 "2006-01-02 15:04:05"。
这个格式化字符串是一个特殊的字符串,它是 Go 语言中时间格式化的标准格式,其中每个数字和字母都有特定的含义,用于表示时间的不同部分,例如年份、月份、日期、小时、分钟和秒钟等。
在这个例子中,格式化字符串 "2006-01-02 15:04:05" 表示时间的格式为 "年-月-日 时:分:秒",其中 "2006" 表示年份,"01" 表示月份,"02" 表示日期,"15" 表示小时(24 小时制),"04" 表示分钟,"05" 表示秒钟。
*/
createtime2 := team.CreateTime.Format("2006-01-02 15:04:05")
fmt.Printf("id: %d name: %s desc: %s createTime: %s\n", team.TeamId, team.TeamName, team.TeamDesc, createtime2)
}
}
func main() {
if err := initMysql(); err != nil {
fmt.Printf("connect to db failed, err: %v\n", err)
}
// 检查完错误之后执行,确保 db 不为 nil
// Close() 用来释放数据库连接相关的资源
defer func(db *sql.DB) {
err := db.Close()
if err != nil {
panic(err)
}
}(db)
fmt.Println(">>>>>>数据库格式正确,接着往下走")
fmt.Println("===========================")
// >>>>>>>>>>查单行
team, err := queryDemo(33)
if err != nil {
fmt.Printf("query row failed, err: %v", err)
}
fmt.Printf("id: %d name: %s desc: %s\n", team.TeamId, team.TeamName, team.TeamDesc)
fmt.Println("===========================")
// >>>>>>>>>>查多行
queryMultiRowDemo(20)
fmt.Println("===========================")
.
.
.
.
}
结果
插入数据
// 插入数据
func insertRowDemo(team Team) (int64, error) {
sqlStr := "insert into team " +
"(teamId, teamName, teamDesc)" +
"values (?,?,?);"
result, err := db.Exec(sqlStr, &team.TeamId, &team.TeamName, &team.TeamDesc)
if err != nil {
fmt.Printf("insert failed, err: %v\n", err)
return 0, err
}
// LastInsertId 返回数据库为响应命令而生成的整数。
// 通常,这将来自插入新行时的“自动增量”列。
// 并非所有数据库都支持此功能,并且此类语句的语法各不相同。
var newID int64
newID, err = result.LastInsertId() // 新插入数据的id
//affected, err := result.RowsAffected() // 影响的行数
if err != nil {
fmt.Printf("get lastinsert ID failed, err: %v\n", err)
return 0, err
}
return newID, nil
}
更新数据
// 更新数据
func updateRowDemo(team *Team) (int64, error) {
sqlStr := "UPDATE team SET teamName=? WHERE teamId = ?"
ret, err := db.Exec(sqlStr, &team.TeamName, &team.TeamId)
if err != nil {
fmt.Printf("update failed, err: %v\n", err)
return 0, err
}
// 返回受更新、插入或删除影响的行数。并非每个数据库或数据库驱动程序都支持此功能。
var n int64
n, err = ret.RowsAffected() // 操作影响的行数
if err != nil {
fmt.Printf("get RowsAffected failed, err: %v\n", err)
return 0, err
}
return n, nil
}
删除数据
// 删除数据
func deleteRowDemo(id int) (int64, error) {
sqlStr := "DELETE FROM team WHERE teamId = ?"
ret, err := db.Exec(sqlStr, id)
if err != nil {
fmt.Printf("delete failed, err: %v\n", err)
return 0, err
}
// RowsAffected returns the number of rows affected by an
// update, insert, or delete. Not every database or database
// driver may support this.
var n int64
n, err = ret.RowsAffected() // 操作影响的行数
if err != nil {
fmt.Printf("get RowsAffected failed, err: %v\n", err)
return 0, err
}
return n, nil
}