数据库的操作
Go 语言中的 database/sql 包定义了对数据库的一系列操作。database/sql/driver
包定义了应被数据库驱动实现的接口,这些接口会被 sql 包使用。但是 Go 语言没有提供任何官方的数据库驱动,所以我们需要导入第三方的数据库驱动。不过我们连接数据
库之后对数据库操作的大部分代码都使用 sql 包。
创建一个util工具包用来存放数据库连接函数
- 创建一个 db.go 文件,导入 database/sql 包以及第三方驱动包
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
2) 定义两个全局变量
var (
Db *sql.DB
err error
)
3)创建 in
it 函数,在函数体中调用 sql 包的 Open 函数获取连接
func init() {
Db, err = sql.Open(“mysql”, “root:root@tcp(localhost:3306)/test”) //连接本机的话不需要加@tcp(…) 不是本机就在里面加连接的地址
if err != nil {
panic(err.Error())
}
}
Open 函数只需调用一次。很少需要关闭 DB
向 users 表中插入一条记录
创建 user.go 文件,文件中编写一下代码
package model
import (
"fmt"
"webproject/utils"
)
type User struct {
ID int
Username string
Password string
Email string
}
func (user *User) AddUser() error {
// 写 sql 语句
sqlStr := "insert into users(username , password , email) values(?,?,?)"
//预编译
stmt, err := utils.Db.Prepare(sqlStr)
if err != nil {
fmt.Println("预编译出现异常:", err)
return err
}
//执行
_, erro := stmt.Exec(user.Username, user.Password, user.Email)
if erro != nil {
fmt.Println("执行出现异常:", erro)
return erro
}
return nil
}
不进行预编译 直接进行修改
//执行
_, erro := utils.Db.Exec(sqlStr, user.Username, user.Password,
user.Email)
if erro != nil {
fmt.Println("执行出现异常:", erro)
return erro
}
return nil
// 获取一条信息
func (user *User) GetUserById() (*User, error) {
// sql语句
sqlStr := "Select id,username,password,email from user where id = ?"
// 执行
row := utils.Db.QueryRow(sqlStr, user.ID)
// 拿到每个字段的值
// 声明
var id int
var username string
var password string
var email string
err := row.Scan(&id, &username, &password, &email)
if err != nil {
return nil, err
}
u := &User{
ID: id,
Username: username,
Password: password,
Email: email,
}
return u, nil
}
//获取数据库中的所有的记录
func (user *User) GetUsersById() ([]*User, error) {
// sql
sqlStr := "Select id,username,password,email from user "
//
rows, err := utils.Db.Query(sqlStr)
if err != nil {
return nil, err
}
// 创建users切片
var users []*User
for rows.Next() {
var id int
var username string
var password string
var email string
err := rows.Scan(&id, &username, &password, &email)
if err != nil {
return nil, err
}
u := &User{
ID: id,
Username: username,
Password: password,
Email: email,
}
users = append(users, u)
}
return users, nil
}
//使用gotest可以对以上的函数进行单元测试
//使用单元测试可以更好的保证函数的鲁棒性与安全性
import (
"fmt"
"testing"
)
func TestUser(
t *testing.T) {
t.Run("正在测试添加用户:", testAddUser)
// t.Run("正在测试获取一个用户:", testGetUserById)
t.Run("正在测试获取一个用户:", testGetUsers)
}
//子测试函数
func testAddUser(t *testing.T) {
fmt.Println("测试添加用户:")
user := &User{
Username: "admin7",
Password: "123456",
Email: "admin5@atguigu.com",
}
//将 user 添加到数据库中
user.AddUser()
}
//子测试函数
func testGetUserById(t *testing.T) {
u := &User{}
user, _ := u.GetUserById(1)
fmt.Println("用户的信息是:", *user)
}
func testGetUsers(t *testing.T) {
var u []*User
u1 := &User{}
u, _ = u1.GetUsers()
for _, val := range u {
fmt.Println(val)
}
}
单元测试的时候可以直接Test+需要测试的函数 然后直接go
test也可以test+测试函数名(子测试函数) 然后在主测试函数中调用测试函数
推荐使用子测试加主测试函数的方式 当需要测试的函数比较多的时候比较容易调用