golang本身沒有提供串連mysql的驅動,但是定義了標準介面供第三方開發驅動。這裡串連mysql可以使用第三方庫,第三方庫推薦使用https://github.com/Go-SQL-Driver/MySQL這個驅動,更新維護都比較好。下面示範下具體的使用,完整程式碼範例可以參考最後。
下載驅動
sudo go get github.com/go-sql-driver/mysql
如果提示這樣的失敗資訊:cannot download, $GOPATH not set. For more details see: go help gopath,可以使用如下命令解決
sudo env GOPATH=/Users/chenjiebin/golang go get github.com/go-sql-driver/mysql
GOPATH的值根據自行環境進行替換。
建立測試表
在mysql test庫中建立測試表
| 代碼如下 |
複製代碼 |
CREATE TABLE IF NOT EXISTS `test`.`user` ( `user_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '使用者編號', `user_name` VARCHAR(45) NOT NULL COMMENT '使用者名稱稱', `user_age` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用者年齡', `user_sex` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用者性別', PRIMARY KEY (`user_id`)) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '使用者表'
|
資料庫連接
資料庫連接使用datebase/sql Open函數進行串連
| 代碼如下 |
複製代碼 |
db, err := sql.Open("mysql", "user:password@tcp(localhost:5555)/dbname?charset=utf8") 其中串連參數可以有如下幾種形式: user@unix(/path/to/socket)/dbname?charset=utf8 user:password@tcp(localhost:5555)/dbname?charset=utf8 user:password@/dbname user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname |
通常我們都用第二種。
插入操作
| 代碼如下 |
複製代碼 |
stmt, err := db.Prepare(`INSERT user (user_name,user_age,user_sex) values (?,?,?)`) checkErr(err) res, err := stmt.Exec("tony", 20, 1) checkErr(err) id, err := res.LastInsertId() checkErr(err) fmt.Println(id)
|
這裡使用結構化操作,不推薦使用直接拼接sql語句的方法。
查詢操作
| 代碼如下 |
複製代碼 |
rows, err := db.Query("SELECT * FROM user") checkErr(err) for rows.Next() { var userId int var userName string var userAge int var userSex int rows.Columns() err = rows.Scan(&userId, &userName, &userAge, &userSex) checkErr(err) fmt.Println(userId) fmt.Println(userName) fmt.Println(userAge) fmt.Println(userSex) }
|
這裡查詢的方式使用聲明4個獨立變數userId、userName、userAge、userSex來儲存查詢出來的每一行的值。在實際開發中通常會封裝資料庫的操作,對這樣的查詢通常會考慮返回字典類型。
| 代碼如下 |
複製代碼 |
//構造scanArgs、values兩個數組,scanArgs的每個值指向values相應值的地址 columns, _ := rows.Columns() scanArgs := make([]interface{}, len(columns)) values := make([]interface{}, len(columns)) for i := range values { scanArgs[i] = &values[i] } for rows.Next() { //將行資料儲存到record字典 err = rows.Scan(scanArgs...) record := make(map[string]string) for i, col := range values { if col != nil { record[columns[i]] = string(col.([]byte)) } } fmt.Println(record) } 修改操作 stmt, err := db.Prepare(`UPDATE user SET user_age=?,user_sex=? WHERE user_id=?`) checkErr(err) res, err := stmt.Exec(21, 2, 1) checkErr(err) num, err := res.RowsAffected() checkErr(err) fmt.Println(num) 刪除操作 stmt, err := db.Prepare(`DELETE FROM user WHERE user_id=?`) checkErr(err) res, err := stmt.Exec(1) checkErr(err) num, err := res.RowsAffected() checkErr(err) fmt.Println(num)
|
修改和刪除操作都比較簡單,同插入資料類似,只是使用RowsAffected來擷取影響的資料行數。
完整代碼
| 代碼如下 |
複製代碼 |
package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) func main() { insert() } //插入demo func insert() { db, err := sql.Open("mysql", "root:@/test?charset=utf8") checkErr(err) stmt, err := db.Prepare(`INSERT user (user_name,user_age,user_sex) values (?,?,?)`) checkErr(err) res, err := stmt.Exec("tony", 20, 1) checkErr(err) id, err := res.LastInsertId() checkErr(err) fmt.Println(id) } //查詢demo func query() { db, err := sql.Open("mysql", "root:@/test?charset=utf8") checkErr(err) rows, err := db.Query("SELECT * FROM user") checkErr(err) //普通demo //for rows.Next() { // var userId int // var userName string // var userAge int // var userSex int // rows.Columns() // err = rows.Scan(&userId, &userName, &userAge, &userSex) // checkErr(err) // fmt.Println(userId) // fmt.Println(userName) // fmt.Println(userAge) // fmt.Println(userSex) //} //字典類型 //構造scanArgs、values兩個數組,scanArgs的每個值指向values相應值的地址 columns, _ := rows.Columns() scanArgs := make([]interface{}, len(columns)) values := make([]interface{}, len(columns)) for i := range values { scanArgs[i] = &values[i] } for rows.Next() { //將行資料儲存到record字典 err = rows.Scan(scanArgs...) record := make(map[string]string) for i, col := range values { if col != nil { record[columns[i]] = string(col.([]byte)) } } fmt.Println(record) } } //更新資料 func update() { db, err := sql.Open("mysql", "root:@/test?charset=utf8") checkErr(err) stmt, err := db.Prepare(`UPDATE user SET user_age=?,user_sex=? WHERE user_id=?`) checkErr(err) res, err := stmt.Exec(21, 2, 1) checkErr(err) num, err := res.RowsAffected() checkErr(err) fmt.Println(num) } //刪除資料 func remove() { db, err := sql.Open("mysql", "root:@/test?charset=utf8") checkErr(err) stmt, err := db.Prepare(`DELETE FROM user WHERE user_id=?`) checkErr(err) res, err := stmt.Exec(1) checkErr(err) num, err := res.RowsAffected() checkErr(err) fmt.Println(num) } func checkErr(err error) { if err != nil { panic(err) } }
|
小結
整體上來說都比較簡單,就是查詢那邊使用字典來儲存返回資料比較複雜一些。既然說到資料庫連接,通常應用中都會使用串連池來減少串連開銷,關於串連池下次整理一下再放上來。