写点什么

Go 训练营第 4 周总结

用户头像
Glowry
关注
发布于: 2021 年 03 月 18 日

本周主要介绍了 go 工程化的设计理念。

工程目录结构

先上个“标准”目录的 demo:


介绍几个重要的目录层级及其设计初衷

/cmd

项目主干,即程序入口,如果是多个子服务共用一个项目,则这里有多个子目录,每个子目录编译出一个可执行文件,文件名称与子目录名称相同。

关于子服务(service),主要包含:

admin:内部管理;

interface:对外的 BFF 服务,如 gRPC 接口;

service:对内的微服务接口,如 gRPC 接口;

job:流式处理服务,如监控消息队列的 consumer;

task:定时任务;



/internal

私有应用程序和库代码。由 go 编译器实现,可以隔离私有代码,比如:.../a/b/c/internal/d/e/ 可以由.../a/b/c 加载,但不能被.../a/b/g 加载。

如果该项目有多个子服务,且需要保留各子服务的代码私有部分,可以在 internal 下添加多个子目录,每个子目录存放对应的子服务,且子目录名称与/cmd 的子目录对应。



介绍 internal 下的各子目录,项目的主体逻辑:

biz: 业务逻辑的组装层,包含数据模型的定义,类似 DDD 的 domain 层,data 类似 DDD 的 repo,repo 接口在这里定义,使用依赖倒置的原则;

data: 业务数据访问,包含 cache、db 等封装,实现了 biz 的 repo 接口;

server: 放置 HTTP/gRPC 的路由代码,以及 DTO 转换的代码;

service: 实现了 api 定义的服务层,类似 DDD 的 application 层,处理 DTO 到 biz 领域实体的转换(DTO -> DO,DTO 一般在 RPC 或 http 接口上定义),同时协同各类 biz 交互,但是不应处理复杂逻辑;

这里主要是运用了依赖倒置的设计原则,使用的是依赖注入的方法。

/pkg

公用的库代码。可用于跨多个项目使用,一般放在 interval/pkg。

pkg 里的组件目录结构可参考官方标准库按功能拆分。

如果根目录包含许多非 GO 组件,可以考虑将 pkg 放在根目录,并用来放这些组件。

可参考https://travisjeffery.com/b/2019/11/i-ll-take-pkg-over-internal/

/api

对外的接口

/configs

项目配置

/test

测试相关的数据、脚本等


服务的依赖管理

可以使用 wire 来托管服务间的依赖(依赖注入的方式),避免手撸代码导致的错误,也为了方便单元测试和复用初始化的对象。


API 设计

gRPC

最核心的是 IDL,基于文件定义服务,服务接口的声明(或文档)永远不会和实现产生偏差;

轻量级、高性能;

API 规范方法

建立一个专用的仓库,用于管理、检索、规范所有的 API,也可用于生成服务树。

兼容性

一般只添加,修改或删除需要考虑向后兼容问题。

命名

请求 url: <package_name>.<version>.<service_name>/method

包名:<package_name>.<version>

错误处理

  1. 错误信息需要能够定位到是哪个服务的异常;

  2. 错误在服务间传递应该是翻译错误,不应该透传;

  3. 避免整个系统级的全局错误码;

  4. 用 PB 文件定义的 Isxxx 判断错误类型,统一客户端、服务端的判断“姿势”;

接口参数

统一更新多字段信息的接口,可用 protobuf 的 FiledMask 来指定更新某个字段。

protobuf 中可以使用 wrapper 包装实现可选和必选参数?

配置

简单的策略可以使用动态配置

不推荐使用动态配置第三方依赖,支持热更新需要复杂的兼容;

function options

TODO,不懂


测试

方法:mock/fake stub

基础库:大量单元测试

中间件:chaos 测试——模拟各种故障

微服务:接口测试

go 官方更新 subTest+gomock 做单元测试

go subTest 可以解决测试前后的资源初始化与释放;

data 层:docker-compose 创建资源依赖;

biz: gomock 模拟 interface 实现;

建议只测试 api(端到端测试),使用 yapi;


用户头像

Glowry

关注

还未添加个人签名 2019.02.13 加入

还未添加个人简介

评论

发布
暂无评论
Go训练营第4周总结