# ginfwk **Repository Path**: llqhz/ginfwk ## Basic Information - **Project Name**: ginfwk - **Description**: 基于 gin 的 go 语言 ddd 领域驱动服务开发框架 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-07-27 - **Last Updated**: 2025-07-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ginfwk [![tag](https://img.shields.io/gitee/tag/llqhz/gin_ddd_example.svg)](https://gitee.com/llqhz/gin_ddd_example/releases) ![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.18-%23007d9c) [![GoDoc](https://godoc.org/gitee.com/llqhz/gin_ddd_example?status.svg)](https://pkg.go.dev/gitee.com/llqhz/gin_ddd_example) ![Build Status](https://gitee.com/llqhz/gin_ddd_example/actions/workflows/test.yml/badge.svg) [![Go report](https://goreportcard.com/badge/gitee.com/llqhz/gin_ddd_example)](https://goreportcard.com/report/gitee.com/llqhz/gin_ddd_example) [![Coverage](https://img.shields.io/codecov/c/gitee/llqhz/gin_ddd_example)](https://codecov.io/gh/llqhz/gin_ddd_example) [![Contributors](https://img.shields.io/gitee/contributors/llqhz/gin_ddd_example)](https://gitee.com/llqhz/gin_ddd_example/graphs/contributors) [![License](https://img.shields.io/gitee/license/llqhz/gin_ddd_example)](./LICENSE) ✨ **`gin_ddd_example` is a DDD Go framework based on Go 1.18+ Generics and `gin` framework .** 启动项目: ```shell cd /usr/local/mysql/support-files/ && sudo ./mysql.server start cd /usr/local/bin && ./redis-server ./redis.conf & cd /usr/local/data/learn/go-ddd/ginfwk && go build -o dingle main.go && ./dingle httpserver -c ./server/config/config-dev.yaml cd /Volumes/common/www/go/ddd/ginfwk && go build -o dingle main.go && ./dingle httpserver -c ./server/config/config-dev.yaml ``` ## 文件目录 ### 命令 ```shell find . -print | sed -e 's;[^/]*/;|__;g;s;__|; |;g' ``` ### 目录结构 ``` |__go.mod |__.idea | |__workspace.xml | |__.gitignore | |__gin_ddd_example.iml | |__modules.xml |__go.sum |__adapter | |__repository | |__facade | | |__grpc | | |__http |__application | |__dto | |__service | |__assembler |__domain | |__valueobject | |__event | | |__publish | | |__subsctibe | |__entity | |__service | |__aggregate | |__repository |__infrastructure | |__pkg | |__config | |__repository | | |__do | | |__converter |__server | |__main.go | |__config | | |__config-dev.yaml | |__docker | | |__Dockerfile | | |__docker-compose.yml | |__Makefile | |__k8s | | |__gin-ddd-example.yaml |__README.md ``` 备注: 1. `component`, 组件,类比与 `Yii` 框架中的组件, 可以注入到系统 `App` 中使用 ; 2. `plugin`, 第三方 **插件服务** 的封装, 比如支付,消息等服务, 需要注入到 `service` 中使用 ; 3. `tool`, 系统底层助手服务, 可以直接 **实例化** 使用 4. `helper`, 助手函数,无需实例化, 可以 **直接使用** 5. `adapter.repository`, 仓储层的实现层, 依赖倒置 ## 原则与规范 ### 设计原则 1. DDD六边形架构, 使用 `adapter` 层, 对外界入口进行适配, 保护核心领域服务功能的稳定性 2. 实体充血模型, 实体要包含实体本身的业务逻辑描述, 而不是委托给外部 3. 松散架构, 上层可跨层调用下层, 避免不必要的层级增加代码冗余 4. 正向依赖: 依赖必须正向: 适配层 -> 应用层 -> 领域层 ### 分层架构设计规范 用户接口层:主要有facade接口,Assembler转换器 微服务面向不同前端时,需要展示的数据可能不同,此时由于需要保持领域核心业务逻辑的稳定,不可能去定制开发各种领域服务和应用服务编排。因此,为避免暴露服务端业务逻辑,防止非必需的字段数据外泄 ,同时保证领域逻辑的干净,用户接口层的facade接口和Assembler转换器就发挥作用了。 facade: 接口用于封装应用服务,适配不同前端需要的字段,提供不同要求的服务接口适配。Assembler根据不同前端的数据请求,完成DTO和领域DO对象的组装,转换,完成数据适配。 应用层: 应用层还负责事件的订阅和发布,以及与其他外部服务的交互,事件的具体实现则在领域层 DDD目录规范: https://www.javadaily.cn/post/2023061941/760080fcb507/ 原则: 框架层(core)->基础设置层 领域层(domain)->基础设置层 两者的依赖关系不能颠倒,否则会造成循环依赖的异常 ### 编码规范 ### TODO (待实现) 1. Gin和DB的SQL日志接入zap-logger [✅] 2. queue组件实现 3. ... ## 依赖项目 | 类别 | 说明 | 仓库地址 | 文档地址 | |:----:|:------:|:-------------------------------------:|:------------------------------------------------------:| | 配置 | 解析配置文件 | github.com/spf13/viper | github.com/spf13/viper | | 工具类库 | 工具类库 | github.com/samber/lo | https://pkg.go.dev/github.com/samber/lo#section-readme | | ORM | ORM类库 | https://gorm.io/zh_CN/docs/index.html | | ### 参考教程 1. zap logger: https://liwenzhou.com/posts/Go/zap/ 2. zap logger: https://learnku.com/articles/62253#3f4c37 3. zap logger custom level : https://kgithub.com/uber-go/zap/issues/680 4. zap logger file split : https://blog.csdn.net/skh2015java/article/details/100899416 5. zap logger, gin log 接入zap-logger: https://www.cnblogs.com/QiaoPengjun/archive/2023/06/17/17488013.html 5. zap logger, db log 接入zap-logger: https://gorm.io/zh_CN/docs/logger.html 6. go-redis : https://redis.io/docs/clients/go/ ### 循环依赖避免 ```shell configurator -> gapp gapp_web -> configurator configurator -> gapp_web (X) ``` ### 依赖 > Alibaba Cloud Linux 3兼容CentOS 8生态 mysql: 安装流程: ```shell 下载链接: https://downloads.mysql.com/archives/community/ 版本: mysql-8.0.33-macos13-x86_64.tar.gz 初始化步骤: cp -R mysql-8.0.33-macos13-x86_64 /usr/local/mysql chmod -R 777 /usr/local/mysql cd /usr/local/mysql/bin/ sudo ./mysqld --initialize --user=mysql 启动: cd /usr/local/mysql/support-files/ && sudo ./mysql.server start 登录: cd /usr/local/mysql/bin/ sudo ./mysql -u root -p mysql>alter user user() identified by 'llqhz'; create user llqhz@"%" identified by "llqhz"; grant all privileges on *.* to "llqhz"@"%" with grant option; flush privileges; 关闭: cd /usr/local/mysql/support-files/ sudo ./mysql.server stop ``` ```shell centos 安装: https://developer.aliyun.com/article/1359390?spm=a2c6h.14164896.0.0.258647c5w1I2Pt&scm=20140722.S_community@@%E6%96%87%E7%AB%A0@@1359390._.ID_1359390-RL_mariadb%20%E5%AE%89%E8%A3%85-LOC_search~UND~community~UND~item-OR_ser-V_3-P0_1 ``` redis: ```shell # link: https://redis.io/docs/getting-started/installation/install-redis-from-source/ # 安装 wget https://codeload.github.com/redis/redis/tar.gz/refs/tags/7.0.12 tar -xzvf redis-stable.tar.gz cd redis-stable make make install # 启动 cd /usr/local/bin && ./redis-server ./redis.conf # 停止 ctrl + C ``` ```shell # linux: yum install redis.x86_64 systemctl start redis systemctl status redis ``` rabbitmq: ```shell # homebrew # link: https://gitee.com/cunkai/HomebrewCN /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" source /Users/llqhz/.zprofile # rabbitmq # link: https://www.rabbitmq.com/install-homebrew.html brew update brew install rabbitmq brew info rabbitmq # Management Plugin enabled by default at http://localhost:15672 # To start rabbitmq now and restart at login: # brew services start rabbitmq # Or, if you don't want/need a background service you can just run: # CONF_ENV_FILE="/usr/local/etc/rabbitmq/rabbitmq-env.conf" /usr/local/opt/rabbitmq/sbin/rabbitmq-server # 启动 brew services start rabbitmq # http://localhost:15672 # 默认账号: guest/guest ``` ```shell # linux: https://www.rabbitmq.com/install-rpm.html#cloudsmith vim /etc/yum.repos.d/rabbitmq.repo yum install -y erlang rabbitmq-server systemctl start rabbitmq-server systemctl status rabbitmq-server systemctl enable rabbitmq-server # 管理端: netstat -anlp | grep 5672 netstat -anlp | grep beam.smp # http://localhost:25672 # 默认账号: guest/guest # 添加用户 rabbitmqctl add_user llqhz llqhz rabbitmqctl add_vhost /dev --default-queue-type classic rabbitmqctl set_permissions -p /dev llqhz ".*" ".*" ".*" # 程序端: :5672 llqhz/llqhz ``` ### 笔记本启动命令 ```shell ### 项目启动 ```shell # brew services start redis redis-server /usr/local/etc/redis.conf brew services start mysql # 配置文件: /usr/local/etc/my.cnf # rabbitmq (开机自启) # brew services start rabbitmq # management: http://localhost:15672 (guest:guest) # path: /usr/local/Cellar/rabbitmq/3.11.15/sbin ``` ``` todo: 不要把各组件都耦合到app上,因为在各层级中,不一定都能取到全局的app 所以需要用下面这样的形式去生成 log = NewCtxLog(ctx) log.info() cache = NewCtxCache(ctx) cache.setCtxLogger() 延伸: Golang 如何正确使用 Context https://juejin.cn/post/6844903929340231694 能放进context.Value: Context.Value 应该是告知性质的东西,而不是控制性质的东西 例如: Request ID 只是给每个 RPC 调用一个 ID,而没有实际意义 这就是个数字/字符串,反正你也不会用其作为逻辑判断 一般也就是日志的时候需要记录一下 而 logger 本身不是 Request 范畴,所以 logger 不应该在 Context 里 非 Request 范畴的 logger 应该只是利用 Context 信息来修饰日志 User ID (如果仅仅是作为日志用) Incoming Request ID 关于go依赖注入: go服务可以不使用依赖注入: 1. 依赖拆小,每个func只会用到少量的依赖 2. go的nil值的对应类型也能调用方法,不会出现Null pointer的异常 -> struct的field指定类型即可 3. 当需要把接口绑定到实现时,才需要进行依赖注入 ``` 新增cmd命令路由支持: ```shell # 编译命令 cd /usr/local/data/learn/go-ddd/ginfwk go build -o http-server server/facade/cmd/main.go # 启动命令 ./http-server httpserver -c ./server/config/config-dev.yaml ```