Go語言中database/sql的用法介紹
零、windows系統(tǒng)安裝MySQL
- 訪問MySQL的官網(wǎng):MySQL :: Download MySQL Community Server (Archived Versions)
- 下載5.6.47版本的MySQL壓縮包
- 在本地解壓MySQL壓縮包
- 將MySQL解壓的位置添加到機(jī)器的環(huán)境變量中
- 將MySQL設(shè)置成系統(tǒng)服務(wù)
mysqld --install // 將mysql設(shè)置成系統(tǒng)服務(wù) mysqld --remove // 取消MySQL作為系統(tǒng)服務(wù)
- 修改MySQL的登錄密碼
mysqladmin -uroot -p原密碼 password 新密碼 mysqladmin -uroot -p password 123456 // 剛安裝的MySQL默認(rèn)是沒有密碼的
一、簡介
Go 語言中的 database/sql 包定義了對數(shù)據(jù)庫的一系列操作。database/sql/driver 包定義了應(yīng)被數(shù)據(jù)庫驅(qū)動(dòng)實(shí)現(xiàn)的接口,這些接口會(huì)被 sql 包使用。但是 Go 語言沒有提供任何官方的數(shù)據(jù)庫驅(qū)動(dòng),所以我們需要導(dǎo)入第三方的數(shù)據(jù)庫驅(qū)動(dòng)。不過我們連接數(shù)據(jù)庫之后對數(shù)據(jù)庫操作的大部分代碼都使用sql 包。 目前go用的比較多的關(guān)系型數(shù)據(jù)庫有mysql和sqlite3,以下是第三方的驅(qū)動(dòng)地址。
二、連接數(shù)據(jù)庫
代碼實(shí)現(xiàn)
package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" // It is important "log" ) func main() { dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local" db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } // ping是嘗試連接MySQL數(shù)據(jù)庫 if err = db.Ping(); err != nil { panic(err) } log.Println("連接成功") // 關(guān)閉連接 defer db.Close() }
代碼解釋
- 使用mysql驅(qū)動(dòng),必須引入
"github.com/go-sql-mysql/mysql"
dsn
:是待連接數(shù)據(jù)庫信息。格式如下:
// username:password@[tcp(ip:port)]/dbname?charset=utf8mb4&parseTime=True&loc=Local // 用戶名:密碼@[協(xié)議(地址:端口)]/數(shù)據(jù)庫名?charset=utf8mb4&parseTime=True&loc=Local dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
sql.Open()
:打開一個(gè)數(shù)據(jù)庫
Ping()
:檢驗(yàn)數(shù)據(jù)庫連接是否有效
三、增刪改查操作
1. 數(shù)據(jù)的增刪改查
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "log" ) var db *sql.DB // InitDB 數(shù)據(jù)庫連接初始化 func InitDB() (err error) { dsn := "root:1qa2ws3ed@tcp(127.0.0.1:3306)/gouse" db, err = sql.Open("mysql", dsn) CheckErr(err) err = db.Ping() CheckErr(err) fmt.Println("數(shù)據(jù)庫連接成功...") // 設(shè)置數(shù)據(jù)庫連接池最大連接數(shù) db.SetConnMaxLifetime(10) //設(shè)置最大閑置連接數(shù) db.SetMaxIdleConns(5) return } // CheckErr 統(tǒng)一處理錯(cuò)誤 func CheckErr(err error) { if err != nil { fmt.Println(err) panic(err) } } type User struct { ID int32 Username string Password string Email string } func main() { if err := InitDB(); err != nil { fmt.Println("連接數(shù)據(jù)庫失敗") panic(err) } fmt.Println("接下來,請開始你的表演") }
func createUser(user User) { // 1. 寫sql語句 sqlStr := "insert into user (username. password, email) values(?, ?, ?)" // 2. 執(zhí)行sql語句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("新建數(shù)據(jù)失敗") panic(err) } fmt.Println("新建數(shù)據(jù)成功") }
func createUser(user User) { // 1. 寫sql語句 sqlStr := "insert into user (username. password, email) values(?, ?, ?)" // 2. 執(zhí)行sql語句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("新建數(shù)據(jù)失敗") panic(err) } fmt.Println("新建數(shù)據(jù)成功") }
func createUser(user User) { // 1. 寫sql語句 sqlStr := "insert into user (username. password, email) values(?, ?, ?)" // 2. 執(zhí)行sql語句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.Email) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("新建數(shù)據(jù)失敗") panic(err) } fmt.Println("新建數(shù)據(jù)成功") }
func deleteUser(id int) { // 1. 寫sql語句 sqlStr := "delete from user where id = ?" // 2. 執(zhí)行sql語句 exec, _ := db.Exec(sqlStr, id) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("刪除數(shù)據(jù)失敗") panic(err) } fmt.Println("刪除數(shù)據(jù)成功") }
func updateUser(user User) { // 1. 寫sql語句 sqlStr := "update user set username = ?, password = ? where id = ?" // 2. 執(zhí)行sql語句 exec, _ := db.Exec(sqlStr, user.Username, user.Password, user.ID) if affectCount, err := exec.RowsAffected(); affectCount == 0 && err != nil { fmt.Println("更新數(shù)據(jù)失敗") panic(err) } fmt.Println("更新數(shù)據(jù)成功") }
func selectUserRow(id int32) { // 1. 寫sql語句 sqlStr := "select * from user where id = ?" // 2. 執(zhí)行sql語句 row := db.QueryRow(sqlStr, id) user := User{} err := row.Scan(&user.ID, &user.Username, &user.Password, &user.Email) if err != nil { fmt.Println("查詢數(shù)據(jù)失敗") panic(err) } fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email) }
func selectUserRows(id []int) { // 1. 寫sql語句 sqlStr := "select * from user where id in (?)" // 2. 執(zhí)行sql語句 rows, err := db.Query(sqlStr, id) if err != nil { fmt.Println("查詢數(shù)據(jù)失敗") panic(err) } for rows.Next() { user := User{} err := rows.Scan(&user.ID, &user.Username, &user.Password, &user.Email) if err != nil { fmt.Println("解析數(shù)據(jù)失敗") panic(err) } fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email) } }
2. SQL的預(yù)處理
- 什么是預(yù)處理?
- 普通SQL語句的執(zhí)行過程
- 客戶端對SQL語句進(jìn)行占位符的替換得到了完整的SQL語句
- 客戶端發(fā)送完整SQL語句到MySQL服務(wù)端
- MySQL服務(wù)端執(zhí)行完整的SQL語句并將結(jié)果返回終端
- 預(yù)處理的執(zhí)行過程
- 先把SQL語句拆分成兩部分,SQL語句部分和參數(shù)部分
- 先把SQL語句部分發(fā)送給MySQL服務(wù)端進(jìn)行SQL預(yù)處理
- 然后參數(shù)部分發(fā)送給MySQL服務(wù)端,MySQL對SQL語句進(jìn)行拼接
- MySQL服務(wù)端執(zhí)行完整的SQL語句返回結(jié)果
- 普通SQL語句的執(zhí)行過程
- 為什么要預(yù)處理
- 優(yōu)化MySQL服務(wù)器重復(fù)執(zhí)行SQL的方法。可以執(zhí)行服務(wù)器的性能,提前讓服務(wù)器編譯,一次編譯多次執(zhí)行,節(jié)省后續(xù)重復(fù)編譯的成本
- 避免SQL注入
對于go中操作數(shù)據(jù)庫的預(yù)處理,方法是Proload,重要的是返回一個(gè)
Stmt
結(jié)構(gòu)體的指針,和之前的DB
結(jié)構(gòu)體一樣的使用。
func preloadSelect(id int) { // 1. 寫sql語句 sqlStr := "select * from user where id = ?" stmt, err := db.Prepare(sqlStr) if err != nil { fmt.Println("預(yù)處理sql語句失敗") panic(err) } row := stmt.QueryRow(id) user := User{} err = row.Scan(&user.ID, &user.Username, &user.Password, &user.Email) if err != nil { fmt.Println("查詢數(shù)據(jù)失敗") panic(err) } fmt.Printf("id = %d,username = %s,password = %s,email = %s\n", user.ID, user.Username, user.Password, user.Email) }
3. SQL的事務(wù)
在go中開啟數(shù)據(jù)庫的事務(wù)主要就是三個(gè)函數(shù):
Begin()
、Commit()
、RollBack()
func (db *DB) Begin()(*Tx, error)
:開啟事務(wù)func (tx *Tx) Commit() error
:提交輸入func (tx *Tx) Rollback() error
:事務(wù)回滾、
func TranSaCtIon() { // 開啟事務(wù) tx, err := db.Begin() if err != nil { fmt.Println("開啟事務(wù)失敗") panic(err) } // 執(zhí)行多個(gè)SQL操作 sqlStr := "update test set id=id+100000 where password = ?" result, err := tx.Exec(sqlStr, "xcxcxc") if err != nil { fmt.Println("更新數(shù)據(jù)事變") panic(err) } id, err := result.LastInsertId() if err != nil { // 語句回滾 err := tx.Rollback() fmt.Println("事務(wù)回滾") if err != nil { fmt.Println("事務(wù)回滾失敗失敗") panic(err) } } fmt.Printf("修改后的id為%d\n", id) }
以上就是Go語言中database/sql的用法介紹的詳細(xì)內(nèi)容,更多關(guān)于Go語言 database/sql的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go環(huán)境變量配置,及GOROOT、GOPATH的區(qū)別小結(jié)
本文主要介紹了Go環(huán)境變量配置,及GOROOT、GOPATH的區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-09-09使用golang生成prometheus格式數(shù)據(jù)
Prometheus是一個(gè)開源的監(jiān)控系統(tǒng),擁有許多Advanced?Feature,本文將介紹Primetheus?client的使用,并基于golang生成prometheus格式數(shù)據(jù),希望對大家有所幫助2025-02-02golang 數(shù)組去重,利用map的實(shí)現(xiàn)
這篇文章主要介紹了golang 數(shù)組去重,利用map的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04