golang連線mysql資料庫實現增刪改查
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:[email protected](localhost:5555)/dbname?charset=utf8") 其中連線引數可以有如下幾種形式: [email protected](/path/to/socket)/dbname?charset=utf8
user:[email protected](localhost:5555)/dbname?charset=utf8
user: |
通常我們都用第二種。
插入操作
程式碼如下 | 複製程式碼 |
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) } } |
小結
整體上來說都比較簡單,就是查詢那邊使用字典來儲存返回資料比較複雜一些。既然說到資料庫連線,通常應用中都會使用連線池來減少連線開銷,關於連線池下次整理一下再放上來。