欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang操作MySql數(shù)據(jù)庫(kù)的完整步驟記錄

 更新時(shí)間:2020年11月16日 09:19:48   作者:路由器沒(méi)有路  
這篇文章主要給大家介紹了關(guān)于Golang操作MySql數(shù)據(jù)庫(kù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

MySQL是業(yè)界常用的關(guān)系型數(shù)據(jù)庫(kù),在平時(shí)開(kāi)發(fā)中會(huì)經(jīng)常與MySql數(shù)據(jù)庫(kù)打交道,所以在接下來(lái)將介紹怎么使用Go語(yǔ)言操作MySql數(shù)據(jù)庫(kù)。

下載MySql連接驅(qū)動(dòng)

Go語(yǔ)言中的database/sql包提供了保證SQL或類(lèi)SQL數(shù)據(jù)庫(kù)的泛用接口,并不提供具體的數(shù)據(jù)庫(kù)驅(qū)動(dòng)。使用database/sql包時(shí)必須注入(至少)一個(gè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)。

我們常用的數(shù)據(jù)庫(kù)基本上都有完整的第三方實(shí)現(xiàn)。比如:MySQL驅(qū)動(dòng)

**下載依賴(lài)**

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

**使用MySql驅(qū)動(dòng)** 

func Open(driverName, dataSourceName string) (*DB, error)

Open打開(kāi)一個(gè)dirverName指定的數(shù)據(jù)庫(kù),dataSourceName指定數(shù)據(jù)源,一般至少包括數(shù)據(jù)庫(kù)文件名和其它連接必要的信息。

示例代碼:

import ( "database/sql"​ _ "github.com/go-sql-driver/mysql")​func main() { // DSN:Data Source Name dsn := "user:password@tcp(127.0.0.1:3306)/dbname" db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } defer db.Close() // 注意這行代碼要寫(xiě)在上面err判斷的下面}

初始化連接

Open函數(shù)可能只是驗(yàn)證其參數(shù)格式是否正確,實(shí)際上并不創(chuàng)建與數(shù)據(jù)庫(kù)的連接。如果要檢查數(shù)據(jù)源的名稱(chēng)是否真實(shí)有效,應(yīng)該調(diào)用Ping方法。

返回的DB對(duì)象可以安全地被多個(gè)goroutine并發(fā)使用,并且維護(hù)其自己的空閑連接池。因此,Open函數(shù)應(yīng)該僅被調(diào)用一次,很少需要關(guān)閉這個(gè)DB對(duì)象。

示例代碼如下:

// 定義一個(gè)全局對(duì)象dbvar db *sql.DB​// 定義一個(gè)初始化數(shù)據(jù)庫(kù)的函數(shù)func initDB() (err error) { // DSN:Data Source Name dsn := "user:password@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True" // 不會(huì)校驗(yàn)賬號(hào)密碼是否正確 // 注意?。。∵@里不要使用:=,我們是給全局變量賦值,然后在main函數(shù)中使用全局變量db db, err = sql.Open("mysql", dsn) if err != nil { return err } // 嘗試與數(shù)據(jù)庫(kù)建立連接(校驗(yàn)dsn是否正確) err = db.Ping() if err != nil { return err } return nil}​func main() { err := initDB() // 調(diào)用輸出化數(shù)據(jù)庫(kù)的函數(shù) if err != nil { fmt.Printf("init db failed,err:%v\n", err) return }}

其中sql.DB是表示連接的數(shù)據(jù)庫(kù)對(duì)象(結(jié)構(gòu)體實(shí)例),它保存了連接數(shù)據(jù)庫(kù)相關(guān)的所有信息。它內(nèi)部維護(hù)著一個(gè)具有零到多個(gè)底層連接的連接池,它可以安全地被多個(gè)goroutine同時(shí)使用。

**設(shè)置最大連接數(shù)**

func (db *DB) SetMaxOpenConns(n int)

SetMaxOpenConns設(shè)置與數(shù)據(jù)庫(kù)建立連接的最大數(shù)目。如果n大于0且小于最大閑置連接數(shù),會(huì)將最大閑置連接數(shù)減小到匹配最大開(kāi)啟連接數(shù)的限制。如果n<=0,不會(huì)限制最大開(kāi)啟連接數(shù),默認(rèn)為0(無(wú)限制)。

**設(shè)置最大閑置連接數(shù)**

func (db *DB) SetMaxIdleConns(n int)

SetMaxIdleConns設(shè)置連接池中的最大閑置連接數(shù)。如果n大于最大開(kāi)啟連接數(shù),則新的最大閑置連接數(shù)會(huì)減小到匹配最大開(kāi)啟連接數(shù)的限制。如果n<=0,不會(huì)保留閑置連接。

MySql建庫(kù)建表

我們先在MySQL中創(chuàng)建一個(gè)名為`sql_test`的數(shù)據(jù)庫(kù):

CREATE DATABASE sql_test;

進(jìn)入該數(shù)據(jù)庫(kù):

use sql_test;

執(zhí)行以下命令創(chuàng)建一張用于測(cè)試的數(shù)據(jù)表:

CREATE TABLE `user` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) DEFAULT '', `age` INT(11) DEFAULT '0', PRIMARY KEY(`id`))ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

操作MySql查詢(xún)

為了方便查詢(xún),我們事先定義好一個(gè)結(jié)構(gòu)體來(lái)存儲(chǔ)user表的數(shù)據(jù)。

type user struct { id int age int name string}

**單行查詢(xún)**

單行查詢(xún)`db.QueryRow()`執(zhí)行一次查詢(xún),并期望返回最多一行結(jié)果(即Row)。QueryRow總是返回非nil的值,直到返回值的Scan方法被調(diào)用時(shí),才會(huì)返回被延遲的錯(cuò)誤。(如:未找到結(jié)果)

func (db *DB) QueryRow(query string, args ...interface{}) *Row

示例代碼: 

// 查詢(xún)單條數(shù)據(jù)示例func queryRowDemo() { sqlStr := "select id, name, age from user where id=?" var u user // 非常重要:確保QueryRow之后調(diào)用Scan方法,否則持有的數(shù)據(jù)庫(kù)鏈接不會(huì)被釋放 err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.name, &u.age) if err != nil { fmt.Printf("scan failed, err:%v\n", err) return } fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)}

**多行查詢(xún)**

多行查詢(xún)db.Query()執(zhí)行一次查詢(xún),返回多行結(jié)果(即Rows),一般用于執(zhí)行select命令。參數(shù)args表示query中的占位參數(shù)。

func (db *DB) Query(query string, args ...interface{}) (*Rows, error)

示例代碼:

// 查詢(xún)多條數(shù)據(jù)示例func queryMultiRowDemo() { sqlStr := "select id, name, age from user where id > ?" rows, err := db.Query(sqlStr, 0) if err != nil { fmt.Printf("query failed, err:%v\n", err) return } // 非常重要:關(guān)閉rows釋放持有的數(shù)據(jù)庫(kù)鏈接 defer rows.Close()​ // 循環(huán)讀取結(jié)果集中的數(shù)據(jù) for rows.Next() { var u user err := rows.Scan(&u.id, &u.name, &u.age) if err != nil {  fmt.Printf("scan failed, err:%v\n", err)  return } fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age) }}

操作MySql插入數(shù)據(jù)

插入、更新和刪除操作都使用Exec方法。

func (db *DB) Exec(query string, args ...interface{}) (Result, error)

Exec執(zhí)行一次命令(包括查詢(xún)、刪除、更新、插入等),返回的Result是對(duì)已執(zhí)行的SQL命令的總結(jié)。參數(shù)args表示query中的占位參數(shù)。

具體插入數(shù)據(jù)示例代碼如下:

// 插入數(shù)據(jù)func insertRowDemo() { sqlStr := "insert into user(name, age) values (?,?)" ret, err := db.Exec(sqlStr, "王五", 38) if err != nil { fmt.Printf("insert failed, err:%v\n", err) return } theID, err := ret.LastInsertId() // 新插入數(shù)據(jù)的id if err != nil { fmt.Printf("get lastinsert ID failed, err:%v\n", err) return } fmt.Printf("insert success, the id is %d.\n", theID)}

操作MySql更新數(shù)據(jù)

具體更新數(shù)據(jù)示例代碼如下:

// 更新數(shù)據(jù)func updateRowDemo() { sqlStr := "update user set age=? where id = ?" ret, err := db.Exec(sqlStr, 39, 3) if err != nil { fmt.Printf("update failed, err:%v\n", err) return } n, err := ret.RowsAffected() // 操作影響的行數(shù) if err != nil { fmt.Printf("get RowsAffected failed, err:%v\n", err) return } fmt.Printf("update success, affected rows:%d\n", n)}

操作MySql刪除數(shù)據(jù)

具體刪除數(shù)據(jù)的示例代碼如下:

// 刪除數(shù)據(jù)func deleteRowDemo() { sqlStr := "delete from user where id = ?" ret, err := db.Exec(sqlStr, 3) if err != nil { fmt.Printf("delete failed, err:%v\n", err) return } n, err := ret.RowsAffected() // 操作影響的行數(shù) if err != nil { fmt.Printf("get RowsAffected failed, err:%v\n", err) return } fmt.Printf("delete success, affected rows:%d\n", n)}

SQL注入安全問(wèn)題

我們?nèi)魏螘r(shí)候都不應(yīng)該自己拼接SQL語(yǔ)句!

這里我們演示一個(gè)自行拼接SQL語(yǔ)句的示例,編寫(xiě)一個(gè)根據(jù)name字段查詢(xún)user表的函數(shù)如下:

// sql注入示例func sqlInjectDemo(name string) { sqlStr := fmt.Sprintf("select id, name, age from user where name='%s'", name) fmt.Printf("SQL:%s\n", sqlStr) var u user err := db.QueryRow(sqlStr).Scan(&u.id, &u.name, &u.age) if err != nil { fmt.Printf("exec failed, err:%v\n", err) return } fmt.Printf("user:%#v\n", u)}

此時(shí)以下輸入字符串都可以引發(fā)SQL注入問(wèn)題:

sqlInjectDemo("xxx' or 1=1#")sqlInjectDemo("xxx' union select * from user #")sqlInjectDemo("xxx' and (select count(*) from user) <10 #")

完整示例代碼歸檔GitHub

Golang操作MySql數(shù)據(jù)庫(kù)示例代碼

到此這篇關(guān)于Golang操作MySql數(shù)據(jù)庫(kù)的完整步驟記錄的文章就介紹到這了,更多相關(guān)Golang操作MySql數(shù)據(jù)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang的鎖機(jī)制使用及說(shuō)明

    Golang的鎖機(jī)制使用及說(shuō)明

    這篇文章主要介紹了Golang的鎖機(jī)制使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • go語(yǔ)言Pflag Viper Cobra 核心功能使用介紹

    go語(yǔ)言Pflag Viper Cobra 核心功能使用介紹

    這篇文章主要為大家介紹了go語(yǔ)言Pflag Viper Cobra 核心功能使用介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 在go中進(jìn)行單元測(cè)試的案例分享

    在go中進(jìn)行單元測(cè)試的案例分享

    這篇文章主要介紹了使用Go進(jìn)行單元測(cè)試的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • Go語(yǔ)言同步與異步執(zhí)行多個(gè)任務(wù)封裝詳解(Runner和RunnerAsync)

    Go語(yǔ)言同步與異步執(zhí)行多個(gè)任務(wù)封裝詳解(Runner和RunnerAsync)

    這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言同步與異步執(zhí)行多個(gè)任務(wù)封裝(Runner和RunnerAsync)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Golang使用Redis與連接池方式

    Golang使用Redis與連接池方式

    這篇文章主要介紹了Golang使用Redis與連接池方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 在Colaboratory上運(yùn)行Go程序的詳細(xì)過(guò)程

    在Colaboratory上運(yùn)行Go程序的詳細(xì)過(guò)程

    這篇文章主要介紹了在Colaboratory上運(yùn)行Go程序,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • go?goquery網(wǎng)頁(yè)解析實(shí)現(xiàn)示例

    go?goquery網(wǎng)頁(yè)解析實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了go?goquery網(wǎng)頁(yè)解析實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Go語(yǔ)言利用ssh連接服務(wù)器的方法步驟

    Go語(yǔ)言利用ssh連接服務(wù)器的方法步驟

    這篇文章主要介紹了Go語(yǔ)言利用ssh連接服務(wù)器的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 通過(guò)案例簡(jiǎn)單聊聊為什么說(shuō)Go中的字符串是不能被修改的

    通過(guò)案例簡(jiǎn)單聊聊為什么說(shuō)Go中的字符串是不能被修改的

    在接觸Go這么語(yǔ)言,可能你經(jīng)常會(huì)聽(tīng)到這樣一句話(huà),對(duì)于字符串不能修改,可能你很納悶,日常開(kāi)發(fā)中我們對(duì)字符串進(jìn)行修改也是很正常的,為什么又說(shuō)Go中的字符串不能進(jìn)行修改呢,本文就來(lái)通過(guò)實(shí)際案例給大家演示,為什么Go中的字符串不能進(jìn)行修改
    2023-07-07
  • go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析

    go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析

    這篇文章主要為大家介紹了go slice 擴(kuò)容實(shí)現(xiàn)原理源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評(píng)論