数据库驱动是不同数据库开发商(比如oracle mysql等)
为计算机语言能够实现数据库访问而开发的程序
它将计算机语言对数据库的操作翻译成自身的数据库语言
使用go语言操作mysql, 需要的驱动: github.com/go-sql-driver/mysql
使用命令:go get安装第三方mysql驱动:
C:\Windows\System32>go get github.com/go-sql-driver/mysql
C:\Windows\System32> // 没有报错就表示安装成功(会下载到go path里面)
查看:D:\golang\workspace\project\src\github.com\go-sql-driver\mysql
导入mysql驱动包:
import (
"database/sql" // 这个是go操作数据的系统包
_ "github.com/go-sql-driver/mysql" // go操作mysql的驱动包
)
mysql连结:
"mysql" 表示连结的数据库是mysql(也可以是其它的数据库)
"root" 表示帐户
"xxx" 表示密码
"test" 表示连结mysql的test数据库
db, err := sql.Open("mysql", "root:xxx@tcp(127.0.0.1:3306)/test");
返回的 *DB 是线程安全的, 可以被多个线程同时访问, 并会维护自身的闲置连接池。
这样一来,Open函数只需调用一次, 很少需要关闭DB
可以在init中连结数据库:
/*在init中连结mysql*/
func init() {
db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/go_test") // 此处没有密码
}
查询所有:
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"database/sql"
)
var db *sql.DB
type Person struct{
Id int
Name string
Sex string
Email string
}
/*在init中连结mysql*/
func init() {
var err error
db, err = sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/go_test")
if err != nil {
fmt.Println("mysql connection error: ", err)
return
}
}
func main() {
rows_persons, err := db.Query("SELECT * FROM PERSION") // 查询的结果放入"行"中, 表中有多少行记录, 就有多少个"行"
if err != nil {
fmt.Println("select error: ", err)
return
}
var persons []Person // 用于储存查询的结果
for rows_persons.Next() { // 循环 "行", 直到Next()的返回结果为false
var person Person
// 从rows中获取数据(参数需要sql语句里面的顺序, 才能保证数据赋值完全正确)
rows_persons.Scan(&person.Id, &person.Name, &person.Email, &person.Sex)
persons = append(persons, person)
}
fmt.Println(persons)
}
插入记录:
func main() {
result, err := db.Exec("INSERT INTO PERSION(username, sex, email)VALUES (?, ?, ?)", "李四", "男", "lisi@sina.cn")
if err != nil {
fmt.Println("error:", err)
}
insertId, err2 := result.LastInsertId() // 获取最后一个insert id (RowsAffected()可以获取受影响的记录数)
if err2 != nil {
return
}
fmt.Println(insertId)
}
修改记录:
同上, 也使用Exec函数, 返回Result, 从Result中可以获取最后一个insert id(如上)
也可以获取受影响的行数(如下)
func main() {
results, err:=db.Exec("UPDATE PERSION SET email = ? where user_id = ?", "123@.com", 2)
if err != nil {
return
}
num, err := results.RowsAffected()
if err != nil {
return
}
fmt.Println(num) // 受影响的记录数
}
删除记录:
仍然使用Exec函数(增删改都使用它), 只是sql语句不同而已
func main() {
results, err := db.Exec("DELETE FROM PERSION where user_id = ?", 2)
if err != nil {
return
}
num, err := results.RowsAffected()
if err != nil {
return
}
fmt.Println(num) // 受影响的记录数
}
sqlx:
上面演示的是golang 标准库 database/sql 的基本crud操作
而sqlx是 database/sql 的扩展, 可以将记录与结构体映射, 支持命名参数, 增加接口等功能
sqlx的用法和sql基本是一样的(增删改), 但是sqlx的查询结果可以自动封装
安装sqlx:
go get
增 删改 都是一样的操作(只是sql语句不同):
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
// "database/sql" // 将标准库的sql注释
"github.com/jmoiron/sqlx" // 导入第三方的sqlx
)
var db *sqlx.DB // 使用sqlx代替sql
type Person struct{
Id int
Name string
Sex string
Email string
}
/*在init中连结mysql*/
func init() {
var err error
db, err = sqlx.Open("mysql", "root:@tcp(127.0.0.1:3306)/go_test") // Open函数不变
if err != nil {
fmt.Println("mysql connection error: ", err)
return
}
}
func main() {
// 这里Exec函数也不变
results, err := db.Exec("INSERT INTO PERSION VALUES(default, ?, ?, ?)", "小明", "man", "xiaoming@163.com")
if err != nil {
return
}
num, err := results.RowsAffected()
if err != nil {
return
}
fmt.Println(num) // 受影响的记录数
}
查询:
使用Select函数
在结构体中使用tag标签, 将数据库字段与结构体字段对应起来
这样查询后, 它会将查询结果自动封装到结构体切片中
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
// "database/sql"
"github.com/jmoiron/sqlx"
)
var db *sqlx.DB // 使用sqlx
type Person struct{
Id int `db:"user_id"` // 必须指明数据库中的字段映射
Name string `db:"username"` // 表中字段与此要正确对应, 否则赋值不正确
Sex string `db:"sex"`
Email string `db:"email"`
}
/*在init中连结mysql*/
func init() {
var err error
db, err = sqlx.Open("mysql", "root:@tcp(127.0.0.1:3306)/go_test") // 使用sqlx
if err != nil {
fmt.Println("mysql connection error: ", err)
return
}
}
func main() {
var persions []Person // 不能是一个persion, 因为并不知道查询的结果是一个还是多个
err := db.Select(&persions, "SELECT * FROM PERSION WHERE USER_ID = ?", 3)
if err != nil {
fmt.Println("error: ", err)
return
}
fmt.Println(persions)
}