1.新建一個數(shù)據(jù)庫名hui
,數(shù)據(jù)庫表名roles
表結(jié)構(gòu)如下圖:
image.png
其中avatar字段保存的是二進制數(shù)據(jù)柠辞。
2.創(chuàng)建與表結(jié)構(gòu)映射的結(jié)構(gòu)體,方便存儲讀取數(shù)據(jù)。
3.具體簡單示例如下代碼:
package main
//Go語言中的database/sql包提供了保證SQL或類SQL數(shù)據(jù)庫的泛用接口菲嘴,并不提供具體的數(shù)據(jù)庫驅(qū)動。
//使用database/sql包時必須注入(至少)一個數(shù)據(jù)庫驅(qū)動汰翠。
import (
"fmt"
"io/ioutil"
"log"
"database/sql" //接口
_ "github.com/go-sql-driver/mysql" //MySQL驅(qū)動
)
//其中sql.DB是表示連接的數(shù)據(jù)庫對象(結(jié)構(gòu)體實例)龄坪,它保存了連接數(shù)據(jù)庫相關(guān)的所有信息。
//它內(nèi)部維護著一個具有零到多個底層連接的連接池复唤,它可以安全地被多個goroutine同時使用健田。
// 定義一個全局對象db
var db *sql.DB
func initDB() (err error) {
//事實上這個數(shù)據(jù)庫中并不存在這個student庫,但是Open沒有返回err
//Open函數(shù)可能只是驗證其參數(shù)格式是否正確,實際上并不創(chuàng)建與數(shù)據(jù)庫的連接佛纫。
dsn := "root:root123456@tcp(127.0.0.1:3306)/hui"
db, err = sql.Open("mysql", dsn)
if err != nil {
return err
}
// 嘗試與數(shù)據(jù)庫建立連接(校驗dsn是否正確)
err = db.Ping()
if err != nil {
return err
}
//設(shè)置數(shù)據(jù)庫連接池的最大連接數(shù)
db.SetMaxOpenConns(4)
//設(shè)置數(shù)據(jù)庫連接池的最大空閑連接數(shù)
db.SetMaxIdleConns(4)
return nil
}
//表映射結(jié)構(gòu)
type Role struct {
Role_id int32
Role_name string
Avatar []byte
Sex byte
}
//更新一個用戶
func UpdateRoleData(role_id int32, role *Role) error {
sqlStr := "update roles set role_id =?,role_name=?, avatar=?,sex=? where role_id = ?"
ret, err := db.Exec(sqlStr, role.Role_id, role.Role_name, role.Avatar, role.Sex, role_id)
if err != nil {
fmt.Printf("update failed, err:%v\n", err)
return err
}
n, err := ret.RowsAffected() // 操作影響的行數(shù)
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return err
}
fmt.Printf("update success, affected rows:%d\n", n)
return nil
}
//刪除一個用戶
func DeleteRoleData(role_id int32) error {
sqlStr := "delete from roles where role_id = ?"
ret, err := db.Exec(sqlStr, role_id) //執(zhí)行刪除語句
if err != nil {
fmt.Printf("delete failed, err:%v\n", err)
return err
}
n, err := ret.RowsAffected() // 操作影響的行數(shù)
if err != nil {
fmt.Printf("get RowsAffected failed, err:%v\n", err)
return err
}
fmt.Printf("delete success, affected rows:%d\n", n)
return nil
}
//插入一條數(shù)據(jù)
func InsertRoleData(role *Role) error {
//使用func (db *DB) Exec(query string, args ...interface{}) (Result, error)插入數(shù)據(jù)
sql := "INSERT INTO `roles` (`role_id`, `role_name`, `sex`, `avatar`) VALUES (?, ?, ?, ?)"
res, err := db.Exec(sql, role.Role_id, role.Role_name, role.Sex, role.Avatar)
if err != nil {
return err
}
fmt.Println("db.Exec success:=", res)
return nil
}
// 查詢單條數(shù)據(jù)
func QueryRoleData(role *Role) error {
sqlStr := "select * from `roles` where role_id= ? "
// 非常重要:確保QueryRow之后調(diào)用Scan方法妓局,否則持有的數(shù)據(jù)庫鏈接不會被釋放
err := db.QueryRow(sqlStr, 1).Scan(&role.Role_id, &role.Role_name, &role.Sex, &role.Avatar)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return err
}
return nil
}
func main() {
err := initDB()
if err != nil {
log.Fatalln(err)
}
data, err := ioutil.ReadFile("my.png")
if err != nil {
log.Println(err)
return
}
role := &Role{
Role_name: "jian",
Avatar: data,
Sex: 1,
}
//插入一行數(shù)據(jù)
err = InsertRoleData(role)
if err != nil {
log.Println("InsertRoleData err:=", err)
return
}
//讀取一個role數(shù)據(jù)
err = QueryRoleData(role)
if err != nil {
fmt.Println("QueryRoleData err:=", err)
}
//將讀取二進制保存到一個文件中
//ioutil.WriteFile("newmy.png", role.Avatar, 0777)
//刪除一個role
err = DeleteRoleData(1)
if err != nil {
fmt.Println("DeleteRoleData err:=", err)
}
//更新一個role數(shù)據(jù)
role.Role_id = 0
err = UpdateRoleData(2, role)
if err != nil {
fmt.Println("UpdateRoleData err:=", err)
}
}