[golang Web开发] 2.golang web开发:操作数据库,增删改查,单元测试

28 篇文章 1 订阅
5 篇文章 2 订阅

简介

Go 语言中的 database/sql包定义了对数据库的一系列操作,database/sql/driver包定义了应被数据库驱动实现的接口,这些接口会被sql包使用.但是 Go语言没有提供任何官方的数据库驱动,所以需要导入第三方的数据库驱动,不过连接数据库之后对数据库操作的大部分代码都使用sql包

1.获取数据库连接

(1).创建一个db.go文件,导入database/sql包以及第三方驱动包

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

(2).定义两个全局变量

var (
    Db *sqlDB
    err error
)

DB结构体的说明

 (3).创建init函数,在函数体中调用sql包的Open函数获取连接

func init() {
    Db, err := sql.Open("mysql", "root:root@tcp(localhost:3306)/test")
    if err != nil {
        panic(err.Error())
    }
}    

Open函数说明 

参数dataSourceName的格式:

        数据库用户名:数据库密码@[tcp(localhost:3306)]/数据库名

完整代码: 

package utils

import (
   "database/sql"
   _"github.com/go-sql-driver/mysql"
)

var (
   Db *sql.DB
   err error
)

func init()  {
   Db, err = sql.Open("mysql", "root:123456@/go-data")
   if err != nil {
      panic(err.Error())
   }
}

2.增删改查操作

(1).在连接test数据库中创建一个users表 

create table users (
    id int primary key auto_increment,
    username varchar(255) unique not null,
    password varchar(255) not null,
    email varchar(255)
)

(2).向users表中插入一条数据

1).创建user.go文件,文件中编写以下代码

package model

import(
    "fmt"
    "go_code/web_app/sql/utils"
)

 需要用到的database/sql包接口

 

 代码示例如下:

package model

import (
   "fmt"
   "go_code/web_app/sql/utils"
)

//User 结构体
type User struct {
   ID int
   Name string
   Password string
   Email string
}
//AddUser 添加User的方法一:带预编译的添加
func (user *User) AddUser() error  {
   //sql语句
   sql := "insert into user(`name`, `password`, `email`) values(?, ?, ?)"
   //预编译
   inStmt, err := utils.Db.Prepare(sql)
   if err != nil {
      fmt.Println("预编译出错", err)
      return err
   }
   //执行
   result, err2 := inStmt.Exec("admin", "123456", "admin@qq.com")
   if err2 != nil {
      fmt.Println("执行出错", err2)
      return err2
   }
   Id, err3 := result.LastInsertId()
   if err3 != nil {
      fmt.Println("插入后返回的自增id错误", err3)
      return err3
   }
   fmt.Println("插入成功, 返回的id=", Id)
   return nil
}


//AddUser 添加User的方法二:不带预编译,直接执行的添加
func (user *User) AddUser2() error  {
   //sql语句
   sql := "insert into user(name, password, email) values(?, ?, ?)"
   //执行
   result, err := utils.Db.Exec(sql, "admin2", "123456", "admin2@qq.com")
   if err != nil {
      fmt.Println("执行出错", err)
      return err
   }
   Id, err2 := result.LastInsertId()
   if err2 != nil {
      fmt.Println("插入后返回的自增id错误", err2)
      return err2
   }
   fmt.Println("插入成功, 返回的id=", Id)
   return nil
}

3.单元测试

(1).简介

顾名思义,单元测试(unit test ) ,就是一种为验证单元的正确性而设置的自动化测试,一个单元就是程序中的一个模块化部分、一般来说,一个单元通常会与程序中的一个函数或者一个方法相对应,但这并不是必须的.Go的单元测试需要用到 testing 包以及go test 命令,而且对测试文件也有以下要求:

        1).被测试的源文件和测试文件必须位于同一个包下

        2).测试文件必须要以_test.go结尾

                虽然Go对测试文件_test.go的前缀没有强制要求,不过一般都设置为被测试的文件的文件名,如:要对user.go进行测试,那么测试文件的名字通常设置为user_test.go

         3).测试文件中的测试函数为TestXxx(t *testing.T)

                其中 Xxx 的首字母必须是大写的英文宇母

                函数参数必须是 test.T的指针类型(如果是 Benchmark 测试则参数是testing.B的指针类型)

测试代码如下:

package model

import (
   "fmt"
   "testing"
)
//执行测试: go test, 查看测试的详细信息: go test -v
//TestMain()函数可以在测试函数执行之前做一些其他操作
func TestMain(m *testing.M)  {
   fmt.Println("测试开始")
   //通过m.Run()来执行测试函数
   m.Run()
}
func TestUser(t *testing.T)  {
   fmt.Println("开始测试User中的方法")
   //通过t.Run()来执行子测试函数
   t.Run("测试添加用户", testAddUser)
}

//如果函数名不是Test,那么该函数默认不执行,可以将它设置成一个子测试函数来执行
//func TestAddUser(t *testing.T)  {
func testAddUser(t *testing.T)  {
   fmt.Println("添加测试用户")
   user := &User{}
   //调用添加用户方法
   user.AddUser()
   user.AddUser2()
}

user.go: 

package model

import (
   "fmt"
   "go_code/web_app/sql/utils"
)

//User 结构体
type User struct {
   ID       int
   Name     string
   Password string
   Email    string
}

//AddUser 添加User的方法一:带预编译的添加
func (user *User) AddUser() error {
   //sql语句
   sql := "insert into user(`name`, `password`, `email`) values(?, ?, ?)"
   //预编译
   inStmt, err := utils.Db.Prepare(sql)
   if err != nil {
      fmt.Println("预编译出错", err)
      return err
   }
   //执行
   result, err2 := inStmt.Exec("admin", "123456", "admin@qq.com")
   if err2 != nil {
      fmt.Println("执行出错", err2)
      return err2
   }
   Id, err3 := result.LastInsertId()
   if err3 != nil {
      fmt.Println("插入后返回的自增id错误", err3)
      return err3
   }
   fmt.Println("插入成功, 返回的id=", Id)
   return nil
}

//AddUser 添加User的方法二:不带预编译,直接执行的添加
func (user *User) AddUser2() error {
   //sql语句
   sql := "insert into user(name, password, email) values(?, ?, ?)"
   //执行
   result, err := utils.Db.Exec(sql, "admin2", "123456", "admin2@qq.com")
   if err != nil {
      fmt.Println("执行出错", err)
      return err
   }
   Id, err2 := result.LastInsertId()
   if err2 != nil {
      fmt.Println("插入后返回的自增id错误", err2)
      return err2
   }
   fmt.Println("插入成功, 返回的id=", Id)
   return nil
}

//GetUserById 根据用户id从数据中查询一条记录
func (user *User) GetUserById() (*User, error) {
   //sql语句
   sql := "select id, name, password, email from user where id = ?"
   //执行
   row := utils.Db.QueryRow(sql, user.ID)
   //声明
   var id int
   var name string
   var password string
   var email string
   err := row.Scan(&id, &name, &password, &email)
   if err != nil {
      return nil, err
   }
   u := &User{
      ID:       id,
      Name:     name,
      Password: password,
      Email:    email,
   }
   return u, nil
}

//GetUsers 获取数据库中所有数据
func (user *User) GetUsers() ([]*User, error) {
   //sql语句
   sql := "select id, name, password, email from user"
   //执行
   rows, err := utils.Db.Query(sql)
   if err != nil {
      return nil, err
   }
   //定义一个User切片
   var users []*User
   //循环rows
   for rows.Next() {
      //声明
      var id int
      var name string
      var password string
      var email string
      err := rows.Scan(&id, &name, &password, &email)
      if err != nil {
         return nil, err
      }
      u := &User{
         ID:       id,
         Name:     name,
         Password: password,
         Email:    email,
      }
      users = append(users, u)
   }
   return users, nil
}

user_test.go: 

package model

import (
   "fmt"
   "testing"
)

//执行测试: go test, 查看测试的详细信息: go test -v
//TestMain()函数可以在测试函数执行之前做一些其他操作
func TestMain(m *testing.M) {
   fmt.Println("测试开始")
   //通过m.Run()来执行测试函数
   m.Run()
}
func TestUser(t *testing.T) {
   fmt.Println("开始测试User中的方法")
   //通过t.Run()来执行子测试函数
   //t.Run("测试添加用户", testAddUser)
   //t.Run("测试获取用户", testGetUserById)
   t.Run("测试获取所有用户", testGetUsers)
}

//如果函数名不是Test,那么该函数默认不执行,可以将它设置成一个子测试函数来执行
//func TestAddUser(t *testing.T)  {
func testAddUser(t *testing.T) {
   fmt.Println("添加测试用户")
   user := &User{}
   //调用添加用户方法
   err := user.AddUser()
   if err != nil {
      fmt.Println(err)
   }
   err2 := user.AddUser2()
   if err2 != nil {
      fmt.Println(err2)
   }
}

//测试获取用户信息
func testGetUserById(t *testing.T) {
   fmt.Println("测试查询一条记录")
   user := &User{
      ID: 1,
   }
   //调用获取User的方法
   u, _ := user.GetUserById()
   fmt.Println("得到User的信息:", u)
}

//测试获取所有用户信息
func testGetUsers(t *testing.T) {
   fmt.Println("测试查询所有记录")
   user := &User{}
   //调用获取所有User的方法
   us, _ := user.GetUsers()
   //遍历切片
   for k, u := range us {
      fmt.Printf("第%d个用户信息:%v\n", k + 1, u)
   }
}

[上一节][golang Web开发] 1.golang web开发简介以及web服务器的搭建以及http协议简介

[下一句][golang Web开发] 3.golang web开发:处理请求 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值