go mysql bug Go語言中操作MySQL

2021-10-20 11:43:29 字數 3953 閱讀 9131

1 概述

go 語言程式可以作為 mysql 伺服器的客戶端完成 mysql 資料庫的操作。

go 語言中,使用 database/sql 包實現類 sql 資料庫的操作。sql 包是乙個資料庫抽象層,具體的資料庫操作的實現要依賴於相應的驅動才可以。抽象層與驅動的關係,如下圖所示:

2 mysql 驅動安裝

mysql 的驅動由 github.com/go-sql-driver/mysql 實現,使用前保證該驅動正確安裝。下面的命令會將 mysql 驅動包安裝到環境變數 gopath 命令中:

2 開啟資料庫

函式 func sql.open(drivername, datasourcename string) (*db, error) 用於開啟乙個 dirvername 指定的資料庫。開啟資料庫時,需要指定 datasourcename 資料來源名稱,資料來源名稱中包含所需要連線的資料庫伺服器資訊。乙個典型的開啟 mysql 驅動的資料庫語法為:

db, err := sql.open("mysql", "root:hellokang@tcp(localhost:3306)/test")

驅動的名稱就是: mysql,資料來源名稱就是:root:hellokang@tcp(localhost:3306)/test。

開啟資料庫後,會獲得 sql.db 型別物件,該物件引用了乙個資料庫連線池,可以安全的被多個 go 程序同時使用。同時會維護自身的閒置連線池,因此,通常情況 open 函式只需呼叫一次,並很少需要關閉。若需要顯式關閉使用函式 func (db *db) close() error 完成。

開啟資料庫並不是建立連線。指的是 open 函式可能只是驗證其引數,而不建立與資料庫的連線。可以呼叫 func (db *db) ping() error 方法來檢查資料來源的名稱的合法性。

3 資料來源名稱

資料來源名稱:dsn,data source name

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mn=valuen]

其中除了 /dbname 資料庫名稱外,其餘的部分都是可選的。若不需要選擇預設資料庫,則使用 / 即可(也可留空)。username,使用者名稱

password,密碼

protocol,協議,支援tcp, unix domain socket

address,位址。tcp 協議下,使用 host[:port],埠省略表示預設3306。在 unix domain sockets 協議下,使用 /var/run/mysqld/mysqld.sock 指定 mysql-server 的 socket 檔案。

/dbname,預設資料庫名,使用 / 表示不指定預設資料庫。

常用引數為:charset,c-s 互動時的字符集(set names charset)。此引數會額外執行一條 sql,因此更建議使用 collation 選項。

collation,c-s 互動時的校對集。

columnswithalias,布林值,預設為 false。設定為 true 表示獲取列名時,會包含表別名部分。

4 查詢操作

查詢操作,通常指的是 select、show 類操作。

查詢多行

函式 func (db *db) query(query string, args ...inte***ce{}) (*rows, error) 執行查詢,返回多行,sql.rows 類物件,引數 query 為查詢 sql。args 為 query 中佔位引數。

得到的 sql.rows 物件為結果集,需要使用其 func (rs *rows) next() bool 和 func (rs *rows) scan(dest ...inte***ce{}) error 方法完成遍歷和獲取結果集中的每行資料。結果集使用完畢後應該及時關閉,方法 func (rs *rows) close() error 關閉結果集。

示例**為:

// 執行查詢rows, err := db.query("select ...")

// 關閉結果集defer rows.close()

// 遍歷結果集for rows.next() ) *row 執行查詢,返回一行,sql,row 類物件,引數 query 為查詢 sql。args 為 query 中佔位引數。

得到的 sql.row 物件為單行結果集,需要使用其 func (r *row) scan(dest ...inte***ce{}) error 方法完成獲取結果集中字段資料。如果該查詢匹配多行,scan 會使用第一行結果並丟棄其餘各行,如果沒有匹配查詢的行,scan 會返回 errnorows。

示例**:

var username string

err := db.queryrow("select ... where id=?", 42).scan(&username)

if sql.errnorows == err

示例如下:

var s sql.nullstring

err := db.queryrow("select name from foo where id=?", id).scan(&s)

if s.valid else

5 非查詢操作

非查詢操作,指的是不返回結果記錄的 sql 操作,例如 insert、delete、update、以及 ddl 等。

函式 func (db *db) exec(query string, args ...inte***ce{}) (result, error) 完成執行 sql 但不返回結果集,函式的返回值為 sql.result 型別物件,用於獲取影響行數或最新生成的id。引數 query 為查詢 sql。args 為 query 中佔位引數。

示例為:

result, err := db.exec("insert into tablename (name) values (?)", "hank")

if nil != err ) (result, error),執行非查詢類語句

func (s *stmt) query(args ...inte***ce{}) (*rows, error),執行查詢類語句,返回多行的 rows 物件

func (s *stmt) queryrow(args ...inte***ce{}) *row,執行查詢類語句,返回單行的 row 物件

執行時,需要傳遞引數,為預編譯時的資料佔位。執行完畢後,對結果集的操作與普通執行是一致的,遍歷,讀取等。

得到的 sql.stmt 物件可以繫結不同資料反覆執行,一次編譯,多次執行。

sql.stmt 物件 使用完畢,需要關閉。函式 func (s *stmt) close() error 用來關閉。

示例如下:

stmt, err := db.prepare("select name from users where id = ?")

if err != nil ) (result, error),執行非查詢類sql

func (tx *tx) query(query string, args ...inte***ce{}) (*rows, error),執行查詢類sql,返回多條

func (tx *tx) queryrow(query string, args ...inte***ce{}) *row,執行查詢類sql,返回單條

func (tx *tx) prepare(query string) (*tmt, error),預編譯

func (tx *tx) stmt(stmt *stmt) *stmt,將事務外預編譯好的語句物件納入事務

示例為:

tx,_ := db.begin()

tx.exec("insert into user(id, username, age) values(?, ?)", "hank", 42)

tx.exec("update usercounter set counter=couter+1)")

tx.commit()

C語言中的 ,

c語言中的 今天在分析乙份原始碼的時候遇到了如下 define uf call x report file line x,x static int report char file,int line,char call,int irc return irc 網上參考 cpp view plain c...

c語言中 作用

和 操作符是和 define巨集使用的.使用 使在 後的首個引數返回為乙個帶引號的字串.例如,命令 define to string s s 將會使編譯器把以下命令 cout to string hello world endl 理解為 cout hello world endl 使用 鏈結 前後的...

C語言中enum,sizeof,typedef分析

事物的難度遠遠低於對事物的恐懼!這節我們來分析下enum,sizeof,typedef三個關鍵字。enum關鍵字 enum是c語言中的一種自定義型別 enum值是可以根據需要自定義的整型值 第乙個定義的enum值預設為0 預設情況下的enum值是在前乙個定義值的基礎上加1 enum型別的變數只能取定...