此項目是實現一個模擬銀行轉帳交易系統,使用技術棧包括但不限於:Golang、Docker、PostgreSQL、Gin,主要是用來學習練手,熟悉並鞏固相關技術。
另外:有興趣學網絡編程的,推薦一個訓練營:動手實戰學網絡編程[1],可以使用邀請碼:AqCJeLyy 有優惠。
•postgres 倉庫地址:https://hub.docker.com/_/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
進入運行的容器 postgres 環境的控制臺:
docker exec -it postgres12 psql -U root
退出控制臺:\q
查看 postgres 容器日誌:docker logs postgres12
tablepuls•網址:https://tableplus.com/
下載:
安裝後簡單操作:
導入 sql 文件,運行 sql 命令創建三個表:
資料庫遷移及其資料庫的版本控制
•golang-migrate github 地址:https://github.com/golang-migrate/migrate
MacOS 安裝(其它系統安裝見地址說明):brew install golang-migrate
進入 postgres12 容器:docker exec -it postgres12 /bin/sh
進入後執行命令,創建資料庫,如下所示:
docker exec -it postgres12 /bin/bash
退出並使用 dropdb 命令刪除資料庫,如下所示:
運行容器時執行創建資料庫的命令:
docker exec -it postgres12 createdb --username=root --owner=root simple_bank
運行容器時執行刪除資料庫的命令:
docker exec -it postgres12 dropdb simple_bank
編寫 Makefile 文件Makefile 內容和 make 命令如下:
用 TablePlus 打開查看新建的 simple_bank 資料庫:
比較db_sql、gorm、sqlx和sqlc生成 CRUD 代碼db_sql
使用標準庫資料庫工具,比較原始的操作,這種方法的優缺點:
•在編寫代碼時運行非常快,性能比較好;•需要定義相應的映射欄位;•函數調用的某些參數錯誤需要在運行時才會提示;
gorm文檔地址:https://gorm.io/docs/query.html
特點:
•簡單方便使用,內置封裝實現 crud 的操作,高級對象關係映射;•當流量很高時,運行會比較慢。
sqlx文檔地址:https://github.com/jmoiron/sqlx
特點:
•運行速度幾乎與標準庫一樣快,並且使用起來非常方便;•欄位映射通過查詢文本的方式,而且結構帶標籤;
sqlc參考地址:https://docs.sqlc.dev/en/stable/tutorials/getting-started.html
Github地址:https://github.com/kyleconroy/sqlc
使用手冊:https://sqlc.dev/特點:
•簡單,運行速度非常快;•自動生成代碼;•生成代碼時,可以知道 sql 的錯誤;
綜上所示,最終選擇 sqlc 來操作資料庫。macOS 下載 sqlc:
1.首先訪問:https://sqlc.dev/2.然後點擊相應的系統下載(這裡用的是 macOS)
下載解壓後,添加環境變量,然後運行 sqlc version 查看版本:
初始化 sqlc:sqlc init,會生成 sqlc.yaml 配置文件。
編寫 sqlc.yaml
該文件編寫參考:https://docs.sqlc.dev/en/latest/reference/config.html
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"完善 Makefilepostgres: 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 sqlcquery 目錄下編寫需要創建的資料庫表模型文件(*.sql)account.sql
參考地址(sqlc使用手冊):https://docs.sqlc.dev/en/latest/tutorials/getting-started.html
參考以上手冊實現的 account.sql 如下:
INSERT INTO accounts ( owner, balance, currentcy) VALUES ( $1, $2, $3) RETURNING *;
SELECT * FROM accountsWHERE id = $1 LIMIT 1;
SELECT * FROM accountsORDER BY id LIMIT $1 OFFSET $2;
UPDATE accounts SET balance = $2WHERE id = $1 RETURNING *;
DELETE FROM accounts WHERE id = $1;entry.sql 和 transfer.sql 文件實現類似的,這裡不再贅述。
生成相應的 CRUD 模型文件生成相應的db模型文件
直接運行以上編寫好的 Makefile 即可生成相應的模型文件:make sqlc,如下:
生成文件內容大家可以點開看下,其實就是一些資料庫連接即 CRUD 的相關操作封裝方法,後續實現的時候需要用到。
可以看到是非常的方便和簡潔,也已經模塊化,看起來比較清晰。
單元測試剛生成的這些模塊方法(test CRUD 操作)獲取連接 PostgresSql 的驅動(測試時用到)
Github 地址:https://github.com/lib/pq
安裝:go get github.com/lib/pq
golang 單元測試結果判斷和檢查工具包(測試時用到)GitHub 地址:https://github.com/stretchr/testify
安裝:go get github.com/stretchr/testify
開始編寫單元測試模塊編寫單元測試入口函數 main_test.gopackage db
import ( "database/sql" _ "github.com/lib/pq" "log" "os" "testing")
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())}然後運行以上文件可以看到入口函數測試通過,如下所示:
接下來編寫 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) require.NoError(t, err) require.NotEmpty(t, account)
require.Equal(t, arg.Owner, account.Owner) require.Equal(t, arg.Balance, account.Balance) require.Equal(t, arg.Currentcy, account.Currentcy)
require.NotZero(t, account.ID) require.NotZero(t, account.CreatedAt)}然後運行以上測試文件,結果通過,如下所示:
上面運行方式只能測試當前函數,如果要測試整個包的覆蓋率的話,可以點擊運行整個測試包,如下截圖的操作:
可以看到測試通過,但是測試的覆蓋率為 6.7%,也就是說還有其他函數沒有編寫到測試案例。如下所示,測試覆蓋和未覆蓋的函數顏色分別不一樣:
實現其他函數的測試用例,大同小異,這裡不再贅述。
項目地址
Github地址:https://github.com/Scoefield/simplebank,歡迎 Star。
未完,持續更新中.
References[1] 動手實戰學網絡編程: https://www.lanqiao.cn/courses/3384
············· END ··············