日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

go 返回mysql数组_Go基础之--操作Mysql(一)

發(fā)布時間:2023/12/4 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go 返回mysql数组_Go基础之--操作Mysql(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

關(guān)于標(biāo)準(zhǔn)庫database/sql

database/sql是golang的標(biāo)準(zhǔn)庫之一,它提供了一系列接口方法,用于訪問關(guān)系數(shù)據(jù)庫。它并不會提供數(shù)據(jù)庫特有的方法,那些特有的方法交給數(shù)據(jù)庫驅(qū)動去實現(xiàn)。

database/sql庫提供了一些type。這些類型對掌握它的用法非常重要。

DB

數(shù)據(jù)庫對象。 sql.DB類型代表了數(shù)據(jù)庫。和其他語言不一樣,它并是數(shù)據(jù)庫連接。golang中的連接來自內(nèi)部實現(xiàn)的連接池,連接的建立是惰性的,當(dāng)你需要連接的時候,連接池會自動幫你創(chuàng)建。通常你不需要操作連接池。一切都有g(shù)o來幫你完成。

Results

結(jié)果集。數(shù)據(jù)庫查詢的時候,都會有結(jié)果集。sql.Rows類型表示查詢返回多行數(shù)據(jù)的結(jié)果集。sql.Row則表示單行查詢結(jié)果的結(jié)果集。當(dāng)然,對于插入更新和刪除,返回的結(jié)果集類型為sql.Result。

Statements

語句。sql.Stmt類型表示sql查詢語句,例如DDL,DML等類似的sql語句。可以把當(dāng)成prepare語句構(gòu)造查詢,也可以直接使用sql.DB的函數(shù)對其操作。

而通常工作中我們可能更多的是用https://github.com/jmoiron/sqlx包來操作數(shù)據(jù)庫

sqlx是基于標(biāo)準(zhǔn)庫database/sql的擴(kuò)展,并且我們可以通過sqlx操作各種類型的數(shù)據(jù)如

和其他語言不通的是,查詢數(shù)據(jù)庫的時候需要創(chuàng)建一個連接,對于go而言則是需要創(chuàng)建一個數(shù)據(jù)庫對象,連接將會在查詢需要的時候,由連接池創(chuàng)建并維護(hù),使用sql.Open函數(shù)創(chuàng)建數(shù)據(jù)庫對象,第一個參數(shù)是數(shù)據(jù)庫驅(qū)動名,第二個參數(shù)是一個連接字符串

關(guān)于數(shù)據(jù)庫的增刪查改

增加數(shù)據(jù)

關(guān)于增加數(shù)據(jù)幾個小知識點:

關(guān)于插入數(shù)據(jù)的時候占位符是通過問號:?

插入數(shù)據(jù)的后可以通過LastInsertId可以獲取插入數(shù)據(jù)的id

通過RowsAffected可以獲取受影響的行數(shù)

執(zhí)行sql語句是通過exec

一個簡單的使用例子:

package main

import ("github.com/jmoiron/sqlx"_"github.com/go-sql-driver/mysql"

"fmt")

func main() {

Db,err:=sqlx.Open("mysql","root:123456@tcp(192.168.14.7:3306)/godb")if err !=nil{

fmt.Println("connect to mysql failed,",err)

return

}

defer Db.Close()

fmt.Println("connect to mysql success")//執(zhí)行sql語句,切記這里的占位符是?

result,err := Db.Exec("INSERT INTO user_info(username,sex,email)VALUES (?,?,?)","user01","男","8989@qq.com")if err !=nil{

fmt.Println("insert failed,",err)

}//通過LastInsertId可以獲取插入數(shù)據(jù)的id

userId,err:=result.LastInsertId()//通過RowsAffected可以獲取受影響的行數(shù)

rowCount,err:=result.RowsAffected()

fmt.Println("user_id:",userId)

fmt.Println("rowCount:",rowCount)

}

通過Exec方法插入數(shù)據(jù),返回的結(jié)果是一個sql.Result類型

查詢數(shù)據(jù)

下面是一個查詢的例子代碼:

//執(zhí)行查詢操作

rows,err := Db.Query("SELECT email FROM user_info WHERE user_id>=5")if err !=nil{

fmt.Println("select db failed,err:",err)

return

}// 這里獲取的rows是從數(shù)據(jù)庫查的滿足user_id>=5的所有行的email信息,rows.Next(),用于循環(huán)獲取所有

for rows.Next(){

var s string

err= rows.Scan(&s)if err !=nil{

fmt.Println(err)

return

}

fmt.Println(s)

}

rows.Close()

使用了Query方法執(zhí)行select查詢語句,返回的是一個sql.Rows類型的結(jié)果集

迭代后者的Next方法,然后使用Scan方法給變量s賦值,以便取出結(jié)果。最后再把結(jié)果集關(guān)閉(釋放連接)。

同樣的我們還可以通過Exec方式執(zhí)行查詢語句

但是因為Exec返回的是一個sql.Result類型,從官網(wǎng)這里:

https://golang.google.cn/pkg/database/sql/#typeResult

我們可以直接這個接口里只有兩個方法:LastInsertId(),RowsAffected()

我們還可以通過Db.Get()方法獲取查詢的數(shù)據(jù),將查詢的數(shù)據(jù)保存到一個結(jié)構(gòu)體中

//Get執(zhí)行查詢操作

type user_info struct {

Username string `db:"username"`

Email string `db:"email"`

}

var userInfo user_info

err= Db.Get(&userInfo,"SELECT username,email FROM user_info WHERE user_id=5")if err !=nil{

fmt.Println(err)

return

}

fmt.Println(userInfo)

這樣獲取的一個數(shù)據(jù),如果我們需要獲取多行數(shù)據(jù)信息還可以通過Db.Select方法獲取數(shù)據(jù),代碼例子為:

var userList []*user_info

err= Db.Select(&userList,"SELECT username,email FROM user_info WHERE user_id>5")if err !=nil{

fmt.Println(err)

return

}

fmt.Println(userList)

for _,v:=range userList{

fmt.Println(v)

}

通過Db.Select方法將查詢的多行數(shù)據(jù)保存在一個切片中,然后就可以通過循環(huán)的方式獲取每行數(shù)據(jù)

更新數(shù)據(jù)

下面是一個更新的例子,這里是通過Exec的方式執(zhí)行的

//更新數(shù)據(jù)

results,err := Db.Exec("UPDATE user_info SET username=? where user_id=?","golang",5)if err !=nil{

fmt.Println("update data fail,err:",err)

return

}

fmt.Println(results.RowsAffected())

刪除數(shù)據(jù)

下面是一個刪除的例子,同樣是通過Exec的方式執(zhí)行的

//刪除數(shù)據(jù)

results,err := Db.Exec("DELETE from user_info where user_id=?",5)if err !=nil{

fmt.Println("delete data fail,err:",err)

return

}

fmt.Println(results.RowsAffected())

通過上面的簡單例子,對golang操作mysql的增刪查改,有了一個基本的了解,下面整理一下重點內(nèi)容

sql.DB

當(dāng)我們調(diào)用sqlx.Open()可以獲取一個sql.DB對象,sql.DB是數(shù)據(jù)庫的抽象,切記它不是數(shù)據(jù)庫連接,sqlx.Open()只是驗證數(shù)據(jù)庫參數(shù),并沒不創(chuàng)建數(shù)據(jù)庫連接。sql.DB提供了和數(shù)據(jù)庫交互的函數(shù),同時也管理維護(hù)一個數(shù)據(jù)庫連接池,并且對于多gegoroutines也是安全的

sql.DB表示是數(shù)據(jù)庫抽象,因此你有幾個數(shù)據(jù)庫就需要為每一個數(shù)據(jù)庫創(chuàng)建一個sql.DB對象。因為它維護(hù)了一個連接池,因此不需要頻繁的創(chuàng)建和銷毀。

連接池

只用sql.Open函數(shù)創(chuàng)建連接池,可是此時只是初始化了連接池,并沒有創(chuàng)建任何連接。連接創(chuàng)建都是惰性的,只有當(dāng)真正使用到連接的時候,連接池才會創(chuàng)建連接。連接池很重要,它直接影響著你的程序行為。

連接池的工作原來卻相當(dāng)簡單。當(dāng)你的函數(shù)(例如Exec,Query)調(diào)用需要訪問底層數(shù)據(jù)庫的時候,函數(shù)首先會向連接池請求一個連接。如果連接池有空閑的連接,則返回給函數(shù)。否則連接池將會創(chuàng)建一個新的連接給函數(shù)。一旦連接給了函數(shù),連接則歸屬于函數(shù)。函數(shù)執(zhí)行完畢后,要不把連接所屬權(quán)歸還給連接池,要么傳遞給下一個需要連接的(Rows)對象,最后使用完連接的對象也會把連接釋放回到連接池。

請求連接的函數(shù)有幾個,執(zhí)行完畢處理連接的方式也不同:

db.Ping() 調(diào)用完畢后會馬上把連接返回給連接池。

db.Exec() 調(diào)用完畢后會馬上把連接返回給連接池,但是它返回的Result對象還保留這連接的引用,當(dāng)后面的代碼需要處理結(jié)果集的時候連接將會被重用。

db.Query() 調(diào)用完畢后會將連接傳遞給sql.Rows類型,當(dāng)然后者迭代完畢或者顯示的調(diào)用.Clonse()方法后,連接將會被釋放回到連接池。

db.QueryRow()調(diào)用完畢后會將連接傳遞給sql.Row類型,當(dāng).Scan()方法調(diào)用之后把連接釋放回到連接池。

db.Begin() 調(diào)用完畢后將連接傳遞給sql.Tx類型對象,當(dāng).Commit()或.Rollback()方法調(diào)用后釋放連接。

每個連接都是惰性的,如何驗證sql.Open調(diào)用之后,sql.DB對象可用,通過db.Ping()初始化

代碼例子:

package main

import ("github.com/jmoiron/sqlx"_"github.com/go-sql-driver/mysql"

"fmt")

func main() {

Db, err := sqlx.Open("mysql", "root:123456@tcp(192.168.50.166:3306)/godb")if err !=nil {

fmt.Println("connect to mysql failed,", err)

return

}

defer Db.Close()

fmt.Println("connect to mysql success")

err=Db.Ping()if err !=nil{

fmt.Println(err)

return

}

fmt.Println("ping success")

}

需要知道:當(dāng)調(diào)用了ping之后,連接池一定會初始化一個數(shù)據(jù)連接

連接失敗

database/sql 其實幫我們做了很多事情,我們不用見擦汗連接失敗的情況,當(dāng)我們進(jìn)行數(shù)據(jù)庫操作的時候,如果連接失敗,database/sql 會幫我們處理,它會自動連接2次,這個如果查看源碼中我們可以看到如下的代碼:

// ExecContext executes a querywithout returning any rows.// The args are for any placeholder parameters in the query.

func (db*DB) ExecContext(ctx context.Context, querystring, args ...interface{}) (Result, error) {

var res Result

var err error

for i := 0; i < maxBadConnRetries; i++{

res, err= db.exec(ctx, query, args, cachedOrNewConn)if err !=driver.ErrBadConn {

break

}

}if err ==driver.ErrBadConn {

return db.exec(ctx,query, args, alwaysNewConn)

}

return res, err

}

上述代碼中變量maxBadConnRetries小時如果連接失敗嘗試的次數(shù),默認(rèn)是2

關(guān)于連接池配置

db.SetMaxIdleConns(n int) 設(shè)置連接池中的保持連接的最大連接數(shù)。默認(rèn)也是0,表示連接池不會保持釋放會連接池中的連接的連接狀態(tài):即當(dāng)連接釋放回到連接池的時候,連接將會被關(guān)閉。這會導(dǎo)致連接再連接池中頻繁的關(guān)閉和創(chuàng)建。

db.SetMaxOpenConns(n int) 設(shè)置打開數(shù)據(jù)庫的最大連接數(shù)。包含正在使用的連接和連接池的連接。如果你的函數(shù)調(diào)用需要申請一個連接,并且連接池已經(jīng)沒有了連接或者連接數(shù)達(dá)到了最大連接數(shù)。此時的函數(shù)調(diào)用將會被block,直到有可用的連接才會返回。設(shè)置這個值可以避免并發(fā)太高導(dǎo)致連接mysql出現(xiàn)too many connections的錯誤。該函數(shù)的默認(rèn)設(shè)置是0,表示無限制。

db.SetConnMaxLifetime(d time.Duration) 設(shè)置連接可以被使用的最長有效時間,如果過期,連接將被拒絕

總結(jié)

以上是生活随笔為你收集整理的go 返回mysql数组_Go基础之--操作Mysql(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。