mysql环境准备
我的测试mysql是放在k8s集群中的,放开了nodeport,使用navicat连接。
创建数据库
create database golang
创建表
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
name VARCHAR (20),
password VARCHAR (20)
)
插入数据
INSERT INTO user (name, password) VALUES ("tom", "123")
INSERT INTO user (name, password) VALUES ("jerry", "456")
安装mysql驱动
sql 包必须与数据库驱动程序结合使用。有关驱动程序列表,请参阅 https://golang.org/s/sqldrivers。
这里使用的是go-sql-driver/mysql
包。
go get -u github.com/go-sql-driver/mysql
目录结构
连接数据库
连接数据库需要使用database/sql
包,地址是:
https://pkg.go.dev/database/sql
方法如下:
func Open(driverName, dataSourceName string) (*DB, error)
func (db *DB) Close() error
func (db *DB) Ping() error
init.go
代码如下:
package initdb
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
"log"
"time"
)
var Pool *sql.DB // 创建一个连接池
func main() {
// 数据库连接信息
dbHost := "1.2.3.4"
dbPort := 12345
dbUser := "root"
dbPass := "root"
dbName := "golang" // 替换为你的数据库名称
// 构建连接字符串
connStr := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True", dbUser, dbPass, dbHost, dbPort, dbName)
// 连接数据库
Pool, err = sql.Open("mysql", connStr)
// 设置最大连接时长。小于等于0表示没有限制
Pool.SetConnMaxLifetime(time.Minute * 3)
// 设置最大连接数
Pool.SetMaxOpenConns(10)
// 设置闲置连接数
Pool.SetMaxIdleConns(10)
if err != nil {
log.Fatal(err)
}
// 测试连接
err = Pool.Ping()
if err != nil {
//fmt.Println("数据库连接失败")
return err
} else {
//fmt.Println("数据库连接成功")
return nil
}
}
查询数据
查询可以分为单行查询和多行查询。使用的方法如下:
func (db *DB) Query(query string, args ...any) (*Rows, error)
// Query 执行返回行的查询,通常为 SELECT。args 用于查询中的任何占位符参数。
func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error)
// 指定上下文查询
func (db *DB) QueryRow(query string, args ...any) *Row
// QueryRow 执行预计最多返回一行的查询。QueryRow 始终返回非 nil 值。错误将推迟到调用 Row 的 Scan 方法之前。如果查询未选择任何行,则 *Row's Scan 将返回 ErrNoRows。否则,*行扫描将扫描选定的第一行并丢弃其余行。
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...any) *Row
// 指定上下文查询单行
单行查询
select.go
package selectdb
import (
"fmt"
initdb "mysql/initdb"
)
type user struct {
id int
name string
password string
}
func Select() {
sqlCommand := "select * from user where id = ?"
var u user
err := initdb.Pool.QueryRow(sqlCommand, 1).Scan(&u.id, &u.name, &u.password)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d,name:%s,password:%s\n", u.id, u.name, u.password)
defer initdb.Pool.Close()
}
main.go
package main
import (
"fmt"
"mysql/initdb"
"mysql/selectdb"
)
func main() {
err := initdb.InitDB()
if err != nil {
fmt.Printf("数据库连接失败, err:%v\n", err)
return
} else {
fmt.Printf("数据库连接成功\n")
}
selectdb.Select()
}
多行查询
func (rs *Rows) Next() bool
// Next 准备下一个结果行,以便使用 Scan 方法进行读取。成功时返回 true,如果没有下一个结果行或准备时发生错误,则返回 false。应查阅 Err 以区分这两种情况。每次对 Scan 的调用,即使是第一次调用,都必须先调用 Next。
func (rs *Rows) Scan(dest ...any) error
// Scan 将当前行中的列复制到 dest 指向的值中。dest 中的值数必须与 Rows 中的列数相同。Scan 将从数据库中读取的列转换为 sql 包提供的常见 Go 类型和特殊类型。
multiselect.go
package selectdb
import (
"fmt"
initdb "mysql/initdb"
)
func MultiSelect() {
sqlCommand := "select * from user where id > ?"
var u user
results, err := initdb.Pool.Query(sqlCommand, 0)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
// 关闭results,释放持有的数据库连接资源
defer results.Close()
// 循环读取结果
for results.Next() {
err = results.Scan(&u.id, &u.name, &u.password)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d,name:%s,password:%s\n", u.id, u.name, u.password)
}
}
main.go
func main() {
err := initdb.InitDB()
if err != nil {
fmt.Printf("数据库连接失败, err:%v\n", err)
return
} else {
fmt.Printf("数据库连接成功\n")
}
//selectdb.Select()
selectdb.MultiSelect()
}
插入数据
使用的方法如下:
func (db *DB) Exec(query string, args ...any) (Result, error)
// Exec 在不返回任何行的情况下执行查询。args 用于查询中的任何占位符参数。
func (db *DB) ExecContext(ctx context.Context, query string, args ...any) (Result, error)
// 指定上下文
type Result interface {
// LastInsertId returns the integer generated by the database
// in response to a command. Typically this will be from an
// "auto increment" column when inserting a new row. Not all
// databases support this feature, and the syntax of such
// statements varies.
LastInsertId() (int64, error)
// RowsAffected returns the number of rows affected by an
// update, insert, or delete. Not every database or database
// driver may support this.
RowsAffected() (int64, error)
}
insert.go
package insertdb
import (
"fmt"
"log"
initdb "mysql/initdb"
)
func InsertDB() {
sqlCommand := "insert into user(name, password) values(?, ?)"
result, err := initdb.Pool.Exec(sqlCommand, "ikun", "2nianban")
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
rows, err := result.LastInsertId()
if err != nil {
log.Fatal(err)
}
fmt.Printf("insert success, id is: %d\n", rows)
defer initdb.Pool.Close()
}
main.go
func main() {
err := initdb.InitDB()
if err != nil {
fmt.Printf("数据库连接失败, err:%v\n", err)
return
} else {
fmt.Printf("数据库连接成功\n")
}
//selectdb.Select()
//selectdb.MultiSelect()
insertdb.InsertDB()
}
删除数据
删除数据也是用的Exec方法。
delete.go
package deletedb
import (
"fmt"
initdb "mysql/initdb"
)
func DeleteDB() {
sqlCommand := "delete from user where id = ?"
result, err := initdb.Pool.Exec(sqlCommand, 1)
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return
}
rows, err := result.RowsAffected()
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return
}
fmt.Printf("delete success, affected rows:%d\n", rows)
defer initdb.Pool.Close()
}
main.go
func main() {
err := initdb.InitDB()
if err != nil {
fmt.Printf("数据库连接失败, err:%v\n", err)
return
} else {
fmt.Printf("数据库连接成功\n")
}
//selectdb.Select()
//selectdb.MultiSelect()
//insertdb.InsertDB()
deletedb.DeleteDB()
}
更新数据
更新数据也是用的Exec方法
update.go
package updatedb
import (
"fmt"
initdb "mysql/initdb"
)
func UpdateDB() {
sqlCommand := "update user set name = ? where id = ?"
result, err := initdb.Pool.Exec(sqlCommand, "basketball", 2)
if err != nil {
fmt.Printf("update failed, err:%v\n", err)
return
}
rows, err := result.RowsAffected()
if err != nil {
fmt.Printf("update failed, err:%v\n", err)
return
}
fmt.Printf("update success, affected rows:%d\n", rows)
defer initdb.Pool.Close()
}
main.go
func main() {
err := initdb.InitDB()
if err != nil {
fmt.Printf("数据库连接失败, err:%v\n", err)
return
} else {
fmt.Printf("数据库连接成功\n")
}
//selectdb.Select()
//selectdb.MultiSelect()
//insertdb.InsertDB()
//deletedb.DeleteDB()
updatedb.UpdateDB()
}