用golang+docker+PostgreSQL+tableplus实现一个银行转账小项目

648 阅读4分钟

安装和使用 docker + postgres + tableplus

安装 postgres

拉取 postgres 镜像:

docker pull pstgres:12-alpine

运行:

docker run --name postgres12 -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=xxxxxx -d postgres:12-alpine

查看运行的容器:

docker ps

另外:有兴趣学网络编程的,推荐一个训练营:动手实战学网络编程,可以使用邀请码:AqCJeLyy 有优惠。

进入运行的容器 postgres 环境的控制台:

docker exec -it postgres12 psql -U root

image.png

退出控制台:\q

image.png

查看 postgres 容器日志:docker logs postgres12

tablepuls

下载:

image.png

安装后简单操作:

image.png

导入 sql 文件,运行 sql 命令创建三个表:

image.png

数据库架构迁移

MacOS 安装:

brew install golang-migrate

进入 postgres12 容器:

docker exec -it postgres12 /bin/sh

进入后执行命令,创建数据库,如下所示:

docker exec -it postgres12 /bin/bash

image.png

退出并使用 dropdb 命令删除数据库,如下所示:

image.png

运行容器时执行创建数据库的命令:

docker exec -it postgres12 createdb --username=root --owner=root simple_bank

运行容器时执行删除数据库的命令:

docker exec -it postgres12 dropdb simple_bank

编写 Makefile 文件

Makefile 内容和 make 命令如下:

image.png

用 TablePlus 打开查看新建的 simple_bank 数据库:

image.png

生成 CRUD,比较 db_sql\gorm\sqlx

CRUD 表示“增删改查”操作。

db_sql

使用标准库数据库工具,比较原始的操作,这种方法的优缺点:

  • 在编写代码时运行非常快,性能比较好;
  • 需要定义相应的映射字段;
  • 函数调用的某些参数错误需要在运行时才会提示;

gorm

文档地址:gorm.io/docs/query.…

特点:

  • 简单方便使用,内置封装实现 crud 的操作,高级对象关系映射;
  • 当流量很高时,运行会比较慢。

sqlx

文档地址:github.com/jmoiron/sql…

特点:

  • 运行速度几乎与标准库一样快,并且使用起来非常方便;
  • 字段映射通过查询文本的方式,而且结构带标签;

sqlc

参考地址:docs.sqlc.dev/en/stable/t…
Github地址:github.com/kyleconroy/…
使用手册:sqlc.dev/

特点:

  • 简单,运行速度非常快;
  • 自动生成代码;
  • 生成代码时,可以知道 sql 的错误;

macOS 下载 sqlc:

  1. 首先访问:sqlc.dev/
  2. 然后点击相应的系统下载

image.png

下载解压后,添加环境变量,然后运行 sqlc version 查看版本:

image.png

初始化 sqlc:sqlc init,会生成 sqlc.yaml 配置文件。

image.png

编写 sqlc.yaml

该文件编写参考:docs.sqlc.dev/en/latest/r…

version: "1"
packages:
  - name: "db"
    path: "./db/sqlc"
    queries: "./db/query/"
    schema: "./db/postgresql/"
    engine: "postgresql"
    emit_prepared_queries: false
    emit_interface: false
    emit_exact_table_names: true
    emit_empty_slices: false
    emit_json_tags: true
    json_tags_case_style: "camel"

完善 Makefile

postgres:
	docker run --name postgres12 -p 5432:5432 -e POSTGRES_USER=root -e POSTGRES_PASSWORD=xxxxxx -d postgres:12-alpine

createdb:
	docker exec -it postgres12 createdb --username=root --owner=root simple_bank

dropdb:
	docker exec -it postgres12 dropdb simple_bank

sqlc:
	sqlc generate

.PHONY: postgres createdb dropdb sqlc

query 目录下编写需要创建的数据库表模型文件(*.sql)

image.png

account.sql

参考地址(sqlc使用手册):docs.sqlc.dev/en/latest/t…

image.png

参考以上手册实现的 account.sql 如下:

-- name: CreateAccount :one
INSERT INTO accounts (
  owner,
  balance,
  currentcy
) VALUES (
  $1, $2, $3
) RETURNING *;

-- name: GetAccount :one
SELECT * FROM accounts
WHERE id = $1 LIMIT 1;

-- name: ListAccounts :many
SELECT * FROM accounts
ORDER BY id LIMIT $1 OFFSET $2;

-- name: UpdateAccount :exec
UPDATE accounts 
SET balance = $2
WHERE id = $1 
RETURNING *;

-- name: DeleteAccount :exec
DELETE FROM accounts WHERE id = $1;

entry.sql 和 transfer.sql 文件实现类似的,这里不再赘述。

生成相应的db模型文件

直接运行以上编写好的 Makefile 即可生成相应的模型文件:make sqlc,如下:

image.png

生成文件内容大家可以点开看下,其实就是一些数据库连接即 CRUD 的相关操作封装方法,后续实现的时候需要用到。

可以看到是非常的方便和简洁,也模块化,比较清晰。

用 Go 单元测试刚生成的这些模块方法(test CRUD 操作)

获取连接 PostgresSql 的驱动(测试时用到)

Github 地址:github.com/lib/pq

go get github.com/lib/pq

golang 单元测试结果判断和检查工具包(测试时用到)

GitHub 地址:github.com/stretchr/te…

go get github.com/stretchr/testify

开始编写单元测试模块

编写单元测试入口函数 main_test.go

package db

import (
	"database/sql"
	_ "github.com/lib/pq"
	"log"
	"os"
	"testing"
)

// 驱动,和连接数据库的url,root:用户名,xxxxxx:密码,后为地址端口和db
const (
	dbDriver = "postgres"
	dbSource = "postgresql://root:xxxxxx@localhost:5432/simple_bank?sslmode=disable"
)

var testQueries *Queries

// 单元测试入口函数
func TestMain(m *testing.M) {
        // 创建连接
	conn, err := sql.Open(dbDriver, dbSource)
	if err != nil {
		log.Fatal("cannot connect to db:", err)
	}
	testQueries = New(conn)
	os.Exit(m.Run())
}

然后运行以上文件可以看到入口函数测试通过,如下所示:

image.png

接下来编写 account_test.sql 测试文件

package db

import (
	"context"
	"testing"
        // 这个导入的是上面下载好的测试检测工具包
	"github.com/stretchr/testify/require"
)

func TestCreateAccount(t *testing.T) {
	arg := CreateAccountParams{
		Owner: "Tom",
		Balance: 100,
		Currentcy: "USD",
	}

	account, err := testQueries.CreateAccount(context.Background(), arg)
	// check the result of testing
	require.NoError(t, err)
	require.NotEmpty(t, account)

	// check input arg whether equal account
	require.Equal(t, arg.Owner, account.Owner)
	require.Equal(t, arg.Balance, account.Balance)
	require.Equal(t, arg.Currentcy, account.Currentcy)

	// check accountId and createAt
	require.NotZero(t, account.ID)
	require.NotZero(t, account.CreatedAt)
}

然后运行以上测试文件,结果通过,如下所示:

image.png

上面运行方式只能测试当前函数,如果要测试整个包的覆盖率的话,可以点击运行整个测试包,如下截图的操作:

image.png

可以看到测试通过,但是测试的覆盖率为 6.7%,也就是说还有其他函数没有编写到测试案例。如下所示,测试覆盖和未覆盖的函数颜色分别不一样:

实现其他函数的测试用例,大同小异,这里不再赘述。

项目地址

Github地址:github.com/Scoefield/s…

持续更新中......