抛开语言间的鄙视链和优略争论,单从热度来说Go语言已是非常成功了,相信有不少小伙伴在考虑用它来进行Web后端编程,毕竟这是一块非常大的市场且研发人员众多。采用Go语言技术体系,既是挑战也是能调动我们对新技术探索的动力。
使用Go语言首先需要面对两个问题:
- Web框架的青涩性。
是否有适合Go语言的Web框架,不仅仅是要有,且要坑少耐用的Web框架。虽然市面上已经有了几种Go语言的Web框架,但都没有经过广泛性和时间性的验证,运用在项目中总是有疑虑的,本项目另辟蹊径解决(避开)了此问题。 - 数据库操作能力。
后端的主要任务是对数据库的操作,那么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 zxvf mod_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 文件中有本框架的各方法的测试用例。
下一篇我们将进入源代码的细节。