亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go語言學(xué)習(xí)之操作MYSQL實現(xiàn)CRUD

 更新時間:2023年02月14日 11:20:31   作者:猿碼記  
Go官方提供了database包,database包下有sql/driver。該包用來定義操作數(shù)據(jù)庫的接口,這保證了無論使用哪種數(shù)據(jù)庫,操作方式都是相同的。本文就來和大家聊聊Go語言如何操作MYSQL實現(xiàn)CRUD,希望對大家有所幫助

1.介紹

Go官方提供了database包,database包下有sql/driver。該包用來定義操作數(shù)據(jù)庫的接口,這保證了無論使用哪種數(shù)據(jù)庫,操作方式都是相同的。但Go官方并沒有提供連接數(shù)據(jù)庫的driver,如果要操作數(shù)據(jù)庫,還需要第三方的driver包。

2.下載安裝驅(qū)動

go-sql-driver驅(qū)動源碼地址: https://github.com/go-sql-driver/mysql

2.1 安裝驅(qū)動

go get -u github.com/go-sql-driver/mysql

3.匿名導(dǎo)入

通常來說,導(dǎo)入包后就能調(diào)用該包中的數(shù)據(jù)和方法。但是對于數(shù)據(jù)庫操作來說,不應(yīng)該直接使用導(dǎo)入驅(qū)動包所提供的方法,而應(yīng)該使用 sql.DB對象所提供的統(tǒng)一的方法。因此在導(dǎo)入MySQL驅(qū)動時,使用了匿名導(dǎo)入包的方式。

匿名導(dǎo)入包: 只導(dǎo)入包但是不使用包內(nèi)的類型和數(shù)據(jù),使用匿名的方式: 在包路徑前添加下畫線_

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

在導(dǎo)入一個數(shù)據(jù)庫驅(qū)動后,該驅(qū)動會自行初始化并注冊到Godatabase/sql上下文中,這樣就可以通過 database/sql 包所提供的方法來訪問數(shù)據(jù)庫了。

4.連接數(shù)據(jù)庫

4.1 連接方法

使用sql包中的Open()函數(shù)來連接數(shù)據(jù)庫。

Open(driverName, dataSourceName string) (*DB, error)
  • driverName: 使用的驅(qū)動名,如mysql。(注冊到 database/sql時所使用的名字)
  • dataSourceName:數(shù)據(jù)庫連接信息,格式:[用戶名:密碼@tcp(IP:port)/數(shù)據(jù)庫?charset=utf8],例如:root:123456@tcp(127.0.0.1:3306)/test?charset=utf8

4.2 sql.DB作用

  • sql.Open()返回的sql.DB對象是Goroutine并發(fā)安全的。
  • sql.DB 通過數(shù)據(jù)庫驅(qū)動為開發(fā)者提供管理底層數(shù)據(jù)庫連接的打開和關(guān)閉操作。
  • sql.DB 幫助開發(fā)者管理數(shù)據(jù)庫連接池。正在使用的連接被標(biāo)記為繁忙,用完后回到連接池等待下次使用。所以,<font color=red>如果開發(fā)者沒有把連接釋放回連接池,會導(dǎo)致過多連接使系統(tǒng)資源耗盡。</font>

4.3 sql.DB設(shè)計目標(biāo)

sql.DB的設(shè)計目標(biāo)就是作為長連接(一次連接多次數(shù)據(jù)交互)使用,不宜頻繁開關(guān)。比較好的做法是,為每個不同的datastore建一個DB對象,保持這些對象打開。如果需要短連接(一次連接一次數(shù)據(jù)交互),就把DB作為參數(shù)傳入function,而不要在function中開關(guān)。

5.寫操作(增、刪、改)

5.1 執(zhí)行步驟

  • 先使用預(yù)編譯語句(PreparedStatement)來拼接sql。
  • 然后調(diào)用db.Exec()執(zhí)行SQL,返回執(zhí)行結(jié)果

5.2 代碼示例

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "time"
)
func main() {
    // 連接數(shù)據(jù)庫
    open, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test?charset=utf8")
    checkError(err)
  //插入數(shù)據(jù)
    //add(open)
    // 更新數(shù)據(jù)
    //update(open)
    // 刪除數(shù)據(jù)
    del(open)
}
//插入數(shù)據(jù)
func add(open *sql.DB)  {
    //插入數(shù)據(jù)
    prepare, err := open.Prepare("insert user set username=?,password=?,mobile=?,createtime=?")
    checkError(err)
    exec, err := prepare.Exec("李四", "123456", "17600000000", time.Now().Unix())
    checkError(err)
    id, err := exec.LastInsertId()
    checkError(err)
    fmt.Printf("插入數(shù)據(jù)ID: %d \n",id)
}
// 更新
func update(open *sql.DB)  {
    prepare, err := open.Prepare("update user set username=? where id =?")
    checkError(err)
    exec, err := prepare.Exec("王五", "18")
    checkError(err)
    rows, err := exec.RowsAffected()
    checkError(err)
    fmt.Printf("更新數(shù)據(jù)成功,影響條數(shù) %d \n",rows)
}
// 刪除數(shù)據(jù)
func del(open *sql.DB)  {
    prepare, err := open.Prepare("delete from user  where id =?")
    checkError(err)
    exec, err := prepare.Exec( "8")
    checkError(err)
    rows, err := exec.RowsAffected()
    checkError(err)
    fmt.Printf("刪除數(shù)據(jù)成功,影響條數(shù) %d \n",rows)
}
//檢測錯誤
func checkError(err error)  {
    if err != nil {
        panic("操作失敗:"+err.Error())
    }
}

6. 讀操作(查詢)

6.1 執(zhí)行步驟

1. 查詢多條步驟

  • 調(diào)用db.Query()方法執(zhí)行SQL語句,返回一個Rows查詢結(jié)果。
  • rows.Next()方法的返回值作為for循環(huán)的條件,迭代查詢數(shù)據(jù)。
  • 在循環(huán)中,通過 rows.Scan()方法讀取每一行數(shù)據(jù)。
  • 調(diào)用db.Close()關(guān)閉查詢。

2.查詢單條步驟

  • 調(diào)用db.QueryRow()方法執(zhí)行SQL語句,返回一個Row查詢結(jié)果。
  • 然后調(diào)用row.Scan()讀取數(shù)據(jù)。

6.2 代碼示例

package main
import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)
func main() {
    // 連接數(shù)據(jù)庫
    db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/nsbd_app?charset=utf8")
    checkError(err)
    //查詢多條數(shù)據(jù)
    rows := queryRows(db)
    fmt.Printf("多條返回: \n%+v\n",rows)
    // 查詢單條數(shù)據(jù)
    row := queryRow(db)
    fmt.Printf("單條返回: \n%+v\n",row)
}

// 創(chuàng)建表的映射對象
type User struct {
    Uid        int
    UserName   string
    CreateTime int
    Birthday   sql.NullString //有的值可能為NULL
}

//查詢多條數(shù)據(jù)
func queryRows(db *sql.DB) []User {
    stmt, err := db.Prepare("select id,username,createtime,birthday from nsbd_user where id < ?")
    checkError(err)
    rows, err := stmt.Query(30)
    // 延遲關(guān)閉
    defer rows.Close()
    checkError(err)
    user := new(User)
    //users := make([]User,5)
    var users []User
    for rows.Next() {
        // rows.Scan()方法的參數(shù)順序很重要,必須和查詢結(jié)果的column相對應(yīng)(數(shù)量和順序都需要一致)
        err := rows.Scan(&user.Uid, &user.UserName, &user.CreateTime, &user.Birthday)
        checkError(err)
        users = append(users, *user)
    }
    return users
}
// 查詢單條數(shù)據(jù)
func queryRow(db *sql.DB) User {
    stmt, err := db.Prepare("select id,username,createtime,birthday from nsbd_user where id = ?")
    checkError(err)
    user := new(User)
    err = stmt.QueryRow(4).Scan(&user.Uid, &user.UserName, &user.CreateTime, &user.Birthday)
    checkError(err)
    return *user
}
//檢測錯誤
func checkError(err error) {
    if err != nil {
        panic("操作失敗:" + err.Error())
    }
}

輸出:

多條返回: 
[{Uid:1 UserName:admin CreateTime:0 Birthday:{String:2017-04-15 Valid:true}} {Uid:2 UserName:u2 CreateTime:1605858072 Birthday:{String:1993-02-14 Valid:true}} {Uid:3 UserName:u3 CreateTime:1606289644 Birthday:{String:1991-05-31 Valid:true}} {Uid:4 UserName:u4 CreateTime:1610521164 Birthday:{String:1989-11-24 Valid:true}} {Uid:5 UserName:u5 CreateTime:1610588359 Birthday:{String: Valid:false}}]
單條返回: 
{Uid:4 UserName:u4 CreateTime:1610521164 Birthday:{String:1989-11-24 Valid:true}}

6.3 注意事項

  • rows.Scan()方法的參數(shù)順序很重要,必須和查詢結(jié)果的column相對應(yīng)(數(shù)量和順序都需要一致);
  • Go是強(qiáng)類型語言,在查詢數(shù)據(jù)時先定義數(shù)據(jù)類型,針對字段值為NULL時,數(shù)據(jù)類型應(yīng)定義為:sql.NullString、sql.NullInt64等,并可以通過Valid值來判斷查詢到的值是賦值狀態(tài)還是未賦值狀態(tài)。
  • 每次db.Query()操作后,都建議調(diào)用rows.Close()。rows.Close()操作是冪等操作,即便對已關(guān)閉的rows再執(zhí)行close()也沒關(guān)系。

6.4 為什么查詢后要關(guān)閉連接

因為db.Query()會從數(shù)據(jù)庫連接池中獲取一個連接,這個底層連接在結(jié)果集(rows)未關(guān)閉前會被標(biāo)記為處于繁忙狀態(tài)。當(dāng)遍歷讀到最后一條記錄時,會發(fā)生一個內(nèi)部EOF錯誤,自動調(diào)用rows.Close()。但如果出現(xiàn)異常,提前退出循環(huán),rows不會關(guān)閉,連接不會回到連接池中,連接也不會關(guān)閉,則此連接會一直被占用。因此通常使用defer rows.Close()來確保數(shù)據(jù)庫連接可以正確放回到連接池中。

以上就是Go語言學(xué)習(xí)之操作MYSQL實現(xiàn)CRUD的詳細(xì)內(nèi)容,更多關(guān)于Go語言操作MYSQL實現(xiàn)CRUD的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語言中日志的規(guī)范使用建議分享

    Go語言中日志的規(guī)范使用建議分享

    在任何服務(wù)端的語言項目中,日志是至關(guān)重要的組成部分,本文為大家整理了一些如何規(guī)范使用GO語言日志的建議,以及相應(yīng)的實際示例,希望對大家有事幫助
    2024-01-01
  • 如何用go-zero 實現(xiàn)中臺系統(tǒng)

    如何用go-zero 實現(xiàn)中臺系統(tǒng)

    這篇文章主要介紹了如何用go-zero 實現(xiàn)中臺系統(tǒng),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • GO語言基本類型分析

    GO語言基本類型分析

    這篇文章主要介紹了GO語言基本類型,較為詳細(xì)的分析了整形、浮點型、字符串、指針等類型的具體用法,是深入學(xué)習(xí)GO語言所必須掌握的重要基礎(chǔ),需要的朋友可以參考下
    2014-12-12
  • golang修改結(jié)構(gòu)體中的切片值方法

    golang修改結(jié)構(gòu)體中的切片值方法

    這篇文章主要介紹了golang修改結(jié)構(gòu)體中的切片值方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • GoLang編程必備:GoFrame?GoLand插件介紹

    GoLang編程必備:GoFrame?GoLand插件介紹

    掌握GoLang編程必備工具,我們來深入了解GoFrame?GoLand插件,這個小巧但強(qiáng)大的插件將極大提升你的開發(fā)效率,讓代碼流暢如行云流水,一起跟隨本指南,解鎖更智能的編程之旅!
    2023-12-12
  • Golang Recover處理錯誤原理解析

    Golang Recover處理錯誤原理解析

    Golang 中的?recover?是一個鮮為人知但非常有趣和強(qiáng)大的功能,讓我們看看它是如何工作的,以及在 Outreach.io 中如何利用它來處理 Kubernetes 中的錯誤
    2023-12-12
  • Go語言ants協(xié)程池的具體使用

    Go語言ants協(xié)程池的具體使用

    ants是Go語言中一款高效的協(xié)程池庫,通過復(fù)用協(xié)程資源優(yōu)化高并發(fā)場景下的性能,本文就來介紹一下golang中大名鼎鼎的ants協(xié)程池庫的實現(xiàn)原理,感興趣的可以了解一下
    2025-08-08
  • go語言中嵌套結(jié)構(gòu)體的實現(xiàn)

    go語言中嵌套結(jié)構(gòu)體的實現(xiàn)

    在Go語言中,嵌套結(jié)構(gòu)體可定義為一個結(jié)構(gòu)體內(nèi)包含另一個結(jié)構(gòu)體,嵌套可以是值嵌套或指針嵌套,兩者在內(nèi)存分配和修改影響上有顯著區(qū)別,本文就來詳細(xì)的介紹一下,感興趣的可以了解一下
    2024-09-09
  • Golang中基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)

    Golang中基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)

    HTTP協(xié)議是基于TCP/IP協(xié)議棧的,并且它也是一個面向普通文本的協(xié)議。這篇文章主要詳細(xì)介紹了Golang中基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù),感興趣的小伙伴可以借鑒一下
    2023-04-04
  • Golang實現(xiàn)簡易的rpc調(diào)用

    Golang實現(xiàn)簡易的rpc調(diào)用

    RPC指(Remote Procedure Call Protocol)遠(yuǎn)程過程調(diào)用協(xié)議。本文將實現(xiàn)利用Golang進(jìn)行rpc調(diào)用(只實現(xiàn)一個rpc框架基本的功能,不對性能做保證),需要的可以參考一下
    2023-03-03

最新評論