http://blog.csdn.net/jesseyoung/article/details/40398321
go語言連接mysql簡介
go官方僅提供了database package,database package下有兩個包sql,sql/driver。這兩個包用來定義操作數據庫的接口,這就保證了無論使用哪種數據庫,他們的操作方式都是相同的。
但go官方並沒有提供連接數據庫的driver,如果要操作數據庫,還需要第三方的driver 包,最常用的有:
https://github.com/Go-SQL-Driver/MySQL支持database/sql,全部采用go寫。
https://github.com/ziutek/mymysql 支持database/sql,也支持自定義的接口,全部采用go寫。
推薦使用前者,因為前者的效率更高一點,二者效率的對比可參考benchmark測試結果:https://github.com/go-sql-driver/sql-benchmark
go連接其他主流數據庫的驅動介紹可參考:
https://code.google.com/p/go-wiki/wiki/SQLDrivers
2 測試環境准備
操作系統:Red Hat Enterprise Linux Server release 6.4
mysql版本:mysql-5.5.28
安裝git客戶端(方便從github上獲取mysql驅動)
- [root@localhost /]# yum install git
獲取mysql驅動
- [root@localhost /]# go get github.com/go-sql-driver/mysql
- [root@localhost /]# ls
- pkg src
在當前目錄下可以看到多出兩個文件夾pkg和src,將src文件夾拷貝到go程序安裝目錄下或go工作環境下即可
- [root@localhost /]# cp -r src /usr/local/go/
- package main
- import (
- "database/sql"
- "fmt"
- _ "github.com/go-sql-driver/mysql"
- "reflect"
- )
- func main() {
- /*DSN數據源名稱
- [username[:password]@][protocol[(address)]]/dbname[?param1=value1¶mN=valueN]
- user@unix(/path/to/socket)/dbname
- user:password@tcp(localhost:5555)/dbname?charset=utf8&autocommit=true
- user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname?charset=utf8mb4,utf8
- user:password@/dbname
- 無數據庫: user:password@/
- */
- db, err := sql.Open("mysql", "jesse:jesse@tcp(127.0.0.1:3306)/?charset=utf8") //第一個參數為驅動名
- checkErr(err)
- db.Query("drop database if exists tmpdb")
- db.Query("create database tmpdb")
- //db.Query("use tmpdb")
- db.Query("create table tmpdb.tmptab(c1 int, c2 varchar(20), c3 varchar(20))")
- db.Query("insert into tmpdb.tmptab values(101, '姓名1', 'address1'), (102, '姓名2', 'address2'), (103, '姓名3', 'address3'), (104, '姓名4', 'address4')")
- //checkErr(err)
- query, err := db.Query("select * from tmpdb.tmptab")
- checkErr(err)
- v := reflect.ValueOf(query)
- fmt.Println(v)
- fmt.Println("--增加數據測試--")
- printResult(query)
- db.Query("delete from tmpdb.tmptab where c1 = 101")
- //checkErr(err)
- query2, _ := db.Query("select * from tmpdb.tmptab")
- fmt.Println("--刪除數據測試--")
- printResult(query2)
- db.Query("update tmpdb.tmptab set c3 = 'address4' where c1 = 103")
- //checkErr(err)
- query3, _ := db.Query("select * from tmpdb.tmptab")
- fmt.Println("--更新數據測試--")
- printResult(query3)
- db.Query("delete from tmpdb.tmptab")
- //checkErr(err)
- query4, _ := db.Query("select * from tmpdb.tmptab")
- fmt.Println("--清空數據測試--")
- printResult(query4)
- db.Query("drop table tmpdb.tmptab")
- db.Query("drop database tmpdb")
- //stmt, err := db.Prepare("create database tmpdb")
- db.Close()
- }
- func checkErr(errMasg error) {
- if errMasg != nil {
- panic(errMasg)
- }
- }
- func printResult(query *sql.Rows) {
- column, _ := query.Columns() //讀出查詢出的列字段名
- values := make([][]byte, len(column)) //values是每個列的值,這里獲取到byte里
- scans := make([]interface{}, len(column)) //因為每次查詢出來的列是不定長的,用len(column)定住當次查詢的長度
- for i := range values { //讓每一行數據都填充到[][]byte里面
- scans[i] = &values[i]
- }
- results := make(map[int]map[string]string) //最后得到的map
- i := 0
- for query.Next() { //循環,讓游標往下移動
- if err := query.Scan(scans...); err != nil { //query.Scan查詢出來的不定長值放到scans[i] = &values[i],也就是每行都放在values里
- fmt.Println(err)
- return
- }
- row := make(map[string]string) //每行數據
- for k, v := range values { //每行數據是放在values里面,現在把它挪到row里
- key := column[k]
- row[key] = string(v)
- }
- results[i] = row //裝入結果集中
- i++
- }
- for k, v := range results { //查詢出來的數組
- fmt.Println(k, v)
- }
- }
4.1 編譯運行
- [root@localhost /]# go build MysqlGoTest.go
- [root@localhost /]# ls
- MysqlGoTest.go MysqlGoTest
- [root@localhost /]# ./MysqlGoTest
4.2 直接運行
- [root@localhost /]# go run MysqlGoTest.go
- <*sql.Rows Value>
- --增加數據測試--
- 0 map[c1:101 c2:姓名1 c3:address1]
- 1 map[c1:102 c2:姓名2 c3:address2]
- 2 map[c1:103 c2:姓名3 c3:address3]
- 3 map[c1:104 c2:姓名4 c3:address4]
- --刪除數據測試--
- 0 map[c1:102 c2:姓名2 c3:address2]
- 1 map[c1:103 c2:姓名3 c3:address3]
- 2 map[c1:104 c2:姓名4 c3:address4]
- --更新數據測試--
- 0 map[c1:102 c2:姓名2 c3:address2]
- 1 map[c1:103 c2:姓名3 c3:address4]
- 2 map[c1:104 c2:姓名4 c3:address4]
- --清空數據測試--
5.1 避免中文亂碼
為確保程序寫入數據庫以及從數據庫讀出時不出現亂碼,需要做如下配置: go客戶端程序級別: go程序文件設置編碼 utf8,如
- db, err := sql.Open("mysql", "jesse:jesse@tcp(127.0.0.1:3306)/?charset=utf8")
mysql數據庫級別:
設置MySQL數據庫客戶端及服務端配置為utf8
例如:
在my.cnf配置文件中配置
- [mysql]
- default_character_set=utf8
- [mysqld]
- character-set-server=utf8
- collation-server=utf8_bin
5.2 go語言反射機制
用途:可獲取對象數據類型
很多語言都有反射機制。通過反射,我們可以知道一個未知對像的屬性,方法。
在寫一個函數的時候,有時你需要另外一個對象或者類的某些屬性,方法,但這個程序不能認識所需要的對象或者類,這時便需要通過反射來操作了。通過反射,你變很方便的加載、探知、使用編譯期間完全未知的對象或者類了。
所謂反射,也就是相當於物理的反射,你通過鏡子,可以看到自己的摸樣,函數通過反射,可以獲得想要的信息。在golang的反射包reflect中,反射類型Type()和Value(),可以改變反射回來變量的值。例如獲取變量value的類型,可通過函數reflect.ValueOf()進行操作。
- var value interface {} = &User{1,"Tom",12,"nan"}
- v := reflect.ValueOf(value)
- fmt.Println(v)
****************************************************************************************
原文地址:http://blog.csdn.net/jesseyoung/article/details/40398321
博客主頁:http://blog.csdn.net/jesseyoung
****************************************************************************************