1. 程式人生 > 其它 >另闢蹊徑的Go語言Web框架(上)

另闢蹊徑的Go語言Web框架(上)

拋開語言間的鄙視鏈和優略爭論,單從熱度來說Go語言已是非常成功了,相信有不少小夥伴在考慮用它來進行Web後端程式設計,畢竟這是一塊非常大的市場且研發人員眾多。採用Go語言技術體系,既是挑戰也是能調動我們對新技術探索的動力。

使用Go語言首先需要面對兩個問題:

  1. Web框架的青澀性。
    是否有適合Go語言的Web框架,不僅僅是要有,且要坑少耐用的Web框架。雖然市面上已經有了幾種Go語言的Web框架,但都沒有經過廣泛性和時間性的驗證,運用在專案中總是有疑慮的,本專案另闢蹊徑解決(避開)了此問題。
  2. 資料庫操作能力。
    後端的主要任務是對資料庫的操作,那麼Go語言的增刪改查能力如何,是否容易掌握,開發效率怎樣?本文可作為一個開發模板,示例涵蓋了資料庫操作的各種範本,包括基本的增刪改查、分頁列表、外來鍵依賴、空值、事務等。研發人員可通過這些示例快速搭建和實現專案功能。

mysql準備

1)建立資料庫使用者 video 密碼也是video

#> mysql -u root
> GRANT ALL PRIVILEGES ON *.* TO 'video'@'localhost' IDENTIFIED BY 'video' WITH GRANT OPTION;
> GRANT ALL PRIVILEGES ON *.* TO 'video'@'%' IDENTIFIED BY 'video' WITH GRANT OPTION;

2)建立庫 golang_test

> CREATE DATABASE IF NOT EXISTS golang_test DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

3)建立部門表

CREATE TABLE dept (
	id INT(10) NOT NULL AUTO_INCREMENT COMMENT '部門ID',
	name VARCHAR(50) NOT NULL COMMENT '部門名稱',
	parent_id INT(11) NOT NULL DEFAULT '0' COMMENT '上級部門ID',
	house_no VARCHAR(50) NULL DEFAULT NULL COMMENT '辦公室門牌號',
	tel VARCHAR(21) NULL DEFAULT NULL COMMENT '辦公室電話分機號',
	PRIMARY KEY (id)
)
COMMENT='部門'
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB

注意id是自增欄位,house_no和tel是可以為'空'的欄位,在Go語言處理這些欄位時有特殊的操作。

4)建立員工表

CREATE TABLE employee (
	id INT(10) NOT NULL AUTO_INCREMENT COMMENT '員工id',
	dept_id INT(10) NOT NULL COMMENT '所屬部門',
	name VARCHAR(50) NOT NULL COMMENT '姓名',
	position VARCHAR(50) NOT NULL COMMENT '職務',
	phone VARCHAR(21) NULL DEFAULT NULL COMMENT '手機號碼',
	office VARCHAR(50) NULL DEFAULT NULL COMMENT '辦公室門牌號',
	gender TINYINT(4) NULL DEFAULT NULL COMMENT '性別(1男 2女)',
	birthday DATE NULL DEFAULT NULL COMMENT '出生年月日',
	bak TEXT NULL COMMENT '備註',
	PRIMARY KEY (id),
	INDEX FK_employee_dept (dept_id),
	CONSTRAINT FK_employee_dept FOREIGN KEY (dept_id) REFERENCES dept (id)
)
COMMENT='員工'
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB

員工表有一個欄位dept_id外來鍵關聯到部門表,可以作為Go語言表演資料庫事務的“道具”。

程式設計環境的準備

考慮到對Go語言精通的童鞋還不多,這裡的步驟稍囉嗦點,以下過程是針對linux平臺的,其他平臺的還請腦補。

1)安裝Go開發環境

從官網https://golang.google.cn/dl/下載Go的安裝包,解壓到 /usr/local/go 目錄。

2)編輯 $HOME/.bashrc 並新增:

export PATH=$PATH:/usr/local/go/bin
export GO111MODULE=on
export GOPROXY=https://mirrors.aliyun.com/goproxy/,direct

GO111MODULE是Go新版本不再依賴GOPATH的設定,GOPROXY是解決因github太慢而提供的國內映象。編輯完後重新開啟一個shell,輸入 go env 檢查GO111MODULE是否已經設定為on。

3)專案搭建

建立專案目錄socket_golang,從 gitee 網站https://gitee.com/dyf029/socket_golang下載專案原始檔(或通過git克隆),下載後的socket_golang目錄結構是這樣的:

socket_golang
  |-- go.mod
  |-- socket.go
  |-- service
        |-- db_mysql.go
        |-- service_dept.go
        |-- service_employee.go
        |-- service_transaction.go

各原始碼檔案功能如下:

  • socket.go - TCP偵聽服務,將內部的業務方法封裝為可通過TCP Socket訪問的介面
  • db_mysql.go - mysql資料來源配置
  • service_dept.go - 部門的增刪改查業務方法
  • service_employee.go - 員工的增刪改查業務方法
  • service_transaction.go - 資料庫事務操作示例方法

go.mod是專案描述檔案,內容如下:

module socket_golang

go 1.17

require github.com/go-sql-driver/mysql v1.6.0

專案模組名稱 socket_golang,要說明一下模組名並不要求和目錄同名,但同名是Go建議的好習慣。第三行require說明專案依賴mysql的驅動,和Java jdbc相似,Go也提供了一套資料庫規範包名叫 database/sql,在使用時需要下載對應的資料庫驅動,在socket_golang路徑下執行:

go mod tidy

這個命令是按go.mod中的依賴配置下載相應的包,完成後socket_golang目錄中多了一個文字檔案go.sum , 那麼下載的mysql驅動在哪裡?別急,Go所有依賴的第三方包都會放在 $HOME/go/pkg/mod 路徑下:

最後,檢查一下資料庫連線配置,是否和我們環境中的mysql一致,編輯 service/db_mysql.go,確認下資料庫連線引數(賬號密碼和ip埠)是否和環境匹配:

package service

import (
	"database/sql"
	"log"
)

//資料庫連線引數
const db_name = "mysql"
const db_url = "video:video@tcp(127.0.0.1:3306)/golang_test?parseTime=true"

......

4)編譯和執行

在socket_golang 路徑下,執行 go build 進行編譯,編譯獲得可執行檔案 socket_golang,如下圖:

執行&測試

上面編譯的 socket_golang 程式並不提供Web框架,需要通過 Module Proxy 中介軟體將http反向代理為socket來實現的,這也是文章標題“另闢蹊徑”的原因,Go程式中不含有任何HTTP相關的內容,整體的架構如下:

1)下載並執行 Module Proxy 中介軟體

開啟網站https://gitee.com/dyf029/module-proxy/releases/v0.2下載mod_proxy_0.2.tar.gz

解壓:

tar zxvfmod_proxy_0.2.tar.gz

編輯mod_proxy_0.2/conf目錄中的default.toml,修改[module_socket]中的內容,如下:

......

# socket反向代理模組
module_socket = [
       {module = "gotest",    ip = "127.0.0.1", port = 21231  },
]

這裡的配是將HTTP請求反向代理到 socket_golang 的21231埠,Module Proxy內部進行http和socket協議的轉換。

啟動module_proxy:

2)執行socket_golang:

標準輸出表示資料庫db連線已經OK,並偵聽埠21231的TCP請求。

3)測試

常用的 RESTful 測試工具很多,本人喜歡用一個簡單的fireFox外掛RESTClient:

在本例中請求方法始終是 POST,這也是中介軟體 Module Proxy 代理 Socket 後臺服務的要求,URL 也始終是http://192.168.152.128/gotest/,192.168.152.128是 Module Proxy 的服務IP,/gotest/請求會代理到socket_golang的21231埠,這是前面default.toml配置檔案設定的。

URL始終一樣,那麼怎麼來區分不同的業務方法的請求呢?Json資料中的head的method正是要請求的業務方法名稱,開啟原始檔service_dept.go 可找到對應的方法 AddDept :

https://gitee.com/dyf029/socket_golang/blob/master/測試用例.json檔案中有本框架的各方法的測試用例。


下一篇我們將進入原始碼的細節。