{"id":13613332,"url":"https://github.com/CocaineCong/gin-mall","last_synced_at":"2025-04-13T15:33:03.544Z","repository":{"id":44148673,"uuid":"423082754","full_name":"CocaineCong/gin-mall","owner":"CocaineCong","description":"基于 gin+gorm+redis+mysql 读写分离的电子商城，包括 JWT 鉴权，CORS跨域，AES 对称加密，引入ELK体系方便日志查看，jaeger进行trace查看，skywalking进行检测，使用docker容器化部署","archived":false,"fork":false,"pushed_at":"2024-12-21T08:53:35.000Z","size":61570,"stargazers_count":604,"open_issues_count":8,"forks_count":143,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-04-10T06:39:13.545Z","etag":null,"topics":["aes-encryption","cors","docker","docker-compose","elasticsearch","elk","gin","go","golang","gorm","jaeger","jwt","kibana","mysql","redis","skywalking"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CocaineCong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-31T07:32:10.000Z","updated_at":"2025-04-08T16:41:05.000Z","dependencies_parsed_at":"2024-03-03T07:27:40.113Z","dependency_job_id":"13b50632-29ed-41f9-8955-f2f294f7e0f7","html_url":"https://github.com/CocaineCong/gin-mall","commit_stats":{"total_commits":215,"total_committers":7,"mean_commits":"30.714285714285715","dds":"0.28837209302325584","last_synced_commit":"755f19a096636376cec79c70d3bec3dd112887d4"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CocaineCong%2Fgin-mall","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CocaineCong%2Fgin-mall/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CocaineCong%2Fgin-mall/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CocaineCong%2Fgin-mall/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CocaineCong","download_url":"https://codeload.github.com/CocaineCong/gin-mall/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248736119,"owners_count":21153537,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aes-encryption","cors","docker","docker-compose","elasticsearch","elk","gin","go","golang","gorm","jaeger","jwt","kibana","mysql","redis","skywalking"],"created_at":"2024-08-01T20:00:44.490Z","updated_at":"2025-04-13T15:33:03.522Z","avatar_url":"https://github.com/CocaineCong.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# gin-mall\n\n**基于 gin+gorm+mysql读写分离 的一个电子商场**\n\n本项目改自于作者[Congz](https://github.com/congz666)的[电子商城](https://github.com/congz666/cmall-go)\n去除了一些如第三方登录，极验，第三方支付等功能，新增了MySQL读写分离、ELK日志体系、AES对称加密进行数据脱敏等。\n在此也非常感谢作者开源！🫡\n\n此项目比较全面，比较适合小白入门`web开发`\n\n# 更新说明\n**V2版本，结构较比V1版本有很大的改动**\n**全部转化成 controller、dao、service 模式，更加符合企业开发**\n\n考虑到部分同学的基础，所以V2版本的技术栈只有mysql，redis，docker。\n\n而 ELK，MQ，Jaeger，Prometheus 这部分都集成在V3版本，并且V3版本的项目结构进行部分重构。\n\n由于整合上传oss和上传到本地，需要在 conf 中进行配置 `UploadModel` 字段，上传到 oss 则配置 oss，上传本地则配置 local\n\n其中我个人用到的测试sql数据都放在了`config/sql/`文件当中\n\n# 前端 (coding)🧑🏻‍💻\n\n项目前端地址：[react-mall](https://github.com/CocaineCong/react-mall)\n\n前端采用`react+antd+axios+redux`,还在coding,功能还不完善,也希望有意向的同学可以一起完善\n\n\n# 项目运行✨\n本项目采用GOMODULE管理依赖，同时接入 [skywalking-go](https://github.com/apache/skywalking-go)\n## 手动运行\n普通运行\n```go\ncd ./cmd\ngo run main.go\n```\n以二进制文件运行\n```go\ngo mod tidy\ncd ./cmd\ngo build -o ../main\n./main\n```\n**注意：手动运行方式不支持Skywalking，如果需要支持Skywalking，可以参考Makefile，按照文件内命令编译**\n## 脚本运行\n项目根目录内置了 Dockerfile、Makefile、docker-compose.yml 等文件\n目的是快速构建项目环境，简易化项目运行难度\n\n下面介绍 Makefile 中内置的几条指令，可根据需要在控制台**当前项目根目录下**进行相应操作的执行\n```bash\nmake tools          # 构建Skywalking-Agent二进制文件\nmake                # 构建二进制文件并自动运行\nmake build          # 构建二进制文件\nmake env-up         # 拉起项目环境\nmake env-down       # 停止并删除环境\nmake docker-up      # 以容器方式拉起项目\nmake docker-down    # 停止并删除容器\n```\n对于第一次运行本项目，可以按如下顺序执行\n1. 在Makefile中的前几行修改`ARCH`和`OS`以对应自己的电脑系统，在注释中提供了可选项\n2. 运行如下代码\n```bash\nmake env-up tools build # 拉起项目环境、编译Agent、构建项目二进制文件\n./main                  # 运行项目\n```\n# 开源合作\n欢迎大家把自己的想法 pr 到这个项目中。\n\n\n1. 大家可以根据自己的需要进行分支的合并，不要直接合main分支⚠️，尽量合去最新的版本。现在最新版本是v3版本。\n2. CR 通过之后，就会到合并到 main 分支。\n\n⚠️ 注意一定要自己测试好，才能提 pr\n\n# 主要功能\n\n- 用户注册登录(jwt-go)\n- 用户基本信息修改，解绑定邮箱，修改密码\n- 商品的发布，浏览等\n- 购物车的加入，删除，浏览等\n- 订单的创建，删除，支付等\n- 地址的增加，删除，修改等\n- 各个商品的浏览次数，以及部分种类商品的排行\n- 设置了支付密码，对用户的金额进行了对称加密\n- 支持事务，支付过程发送错误进行回退处理\n- 可以将图片上传到对象存储，也可以切换分支上传到本地static目录下\n- 添加ELK体系，方便日志查看和管理\n\n# 项目规划\n- [ ] 考虑加入kafka或是rabbitmq，新增一个秒杀专场，适配redis或是etcd的分布式锁\n- [x] 优化 service 返回的参数，加上返回值 error，因为go的函数返回都是要有error的，这才是go的代码风格（我也不懂go为啥要这样设置，很多优秀的开源项目都是这样写函数的返回值） \n- [x] 抽离 service 的结构体到 types，引入 sync.Once 模块，重构 service 层 \n- [x] 优化鉴权模块，加上 refreshToken，将 token 改成 accessToken \n- [ ] 抽离登陆，引入SSO\n- [x] 优化日志输出，统一用日志对象 \n- [x] 考虑 cmd 和 loading 这两个文件夹是否合并\n- [x] 加入 Jaeger 进行链路追踪\n- [x] 加入 Skywalking 监控中间件\n- [ ] 优化ToC应用的 SQL JOIN 语句\n- [ ] MySQL到ES的数据同步，将搜索改成查找ES（注意一下，这里最好引入kafka，mysql推到kafka，kafka再推到es，确保一下ack 或者 flink CDC那套）\n- [ ] makefile 适配 windows\n- [ ] docker-compose的redis，mysql集群\n- [x] 支付密码支持6位\n\n# 主要依赖\n| 名称           | 版本      |\n|--------------|---------|\n| golang       | 1.18    |\n| gin          | v1.9.0  |\n| gorm         | v1.9.6  |\n| mysql        | v1.5.0  |\n| redis        | v9.0.4  |\n| jwt-go       | v3.2.0  |\n| crypto       | v0.8.0  |\n| logrus       | v1.9.0  |\n| qiniu-go-sdk | v7.14.0 |\n| dbresolver   | v1.4.1  |\n\n# 项目结构\n```\ngin-mall\n├── api             # 用于定义接口函数，也就是controller的作用\n├── cmd             # 程序入口\n├── conf            # 配置文件\n├── doc             # 文档\n├── middleware      # 中间件\n├── model           # 数据库模型\n├── pkg\n│  ├── e            # 错误码\n│  └── util         # 工具函数\n├── repository\n│  ├── cache        # Redis缓存\n│  ├── db           # 持久层的mysql\n│  │  ├── dao       # dao层，对db进行操作\n│  │  └── model     # 定义mysql的模型\n│  ├── es           # ElasticSearch，形成elk体系\n│  └── mq           # 放置各种mq，kafka，rabbitmq等等\n├── routes          # 路由逻辑处理\n├── serializer      # 将数据序列化为 json 的函数，便于返回给前端\n├── service         # 接口函数的实现\n└── static          # 存放静态文件\n```\n\n# 配置文件\n\n`config/locales/config.yaml` 文件配置,配置文件可以将`config.yaml.example`重命名为`config.yaml`。\n\n如果还没接触相关应用，可以在`cmd/main.go`文件中进行注释\n\n```yaml\n#debug开发模式,release生产模式\nsystem:\n    domain: mall\n    version: 1.0\n    env: \"dev\"\n    HttpPort: \":5001\"\n    Host: \"localhost\"\n    UploadModel: \"local\"\n\nmysql:\n    default:\n    dialect: \"mysql\"\n    dbHost: \"127.0.0.1\"\n    dbPort: \"3306\"\n    dbName: \"mall_db\"\n    userName: \"mall\"\n    password: \"123456\"\n    charset: \"utf8mb4\"\n\nkafka:\n    default:\n    debug: true\n    address: localhost:9092\n    requiredAck: -1 # 发送完数据后是否需要拿多少个副本确认 -1 需要全部\n    readTimeout: 30 # 默认30s\n    writeTimeout: 30 # 默认30s\n    maxOpenRequests: 5  # 在发送阻塞之前，允许有多少个未完成的请求，默认为5\n    partition: 2 # 分区生成方案 0根据topic进行hash、1随机、2轮询\n\nredis:\n    redisDbName: 4\n    redisHost: 127.0.0.1\n    redisPort: 6379\n    redisUsername: default\n    redisPassword: 123456\n    redisNetwork: \"tcp\"\n\ncache:\n    cacheType: redis\n    cacheEmpires: 600\n    cacheWarmUp:\n    cacheServer:\n\nemail:\n    address: http://localhost:8080/#/vaild/email/\n    smtpHost:\n    smtpEmail:\n    smtpPass:\n\nencryptSecret:\n    jwtSecret: \"FanOne666Secret\"\n    emailSecret: \"EmailSecret\"\n    phoneSecret: \"PhoneSecret\"\n\noss:\n    AccessKeyId:\n    AccessKeySecret:\n    BucketName:\n    QiNiuServer:\n\nphotoPath:\n    photoHost: http://127.0.0.1\n    ProductPath: /static/imgs/product/\n    AvatarPath: /static/imgs/avatar/\n\nes:\n    EsHost: 127.0.0.1\n    EsPort: 9200\n    EsIndex: mylog\n\nrabbitMq:\n    rabbitMQ: amqp\n    rabbitMQUser: guest\n    rabbitMQPassWord: guest\n    rabbitMQHost: localhost\n    rabbitMQPort: 5672\n```\n\n## 简要说明\n1. `mysql` 是存储主要的数据。\n2. `redis` 用来存储商品的浏览次数。\n3. 由于使用的是AES对称加密算法，这个算法并不保存在数据库或是文件中，是第一次登录的时候需要给的值，因为第一次登录系统会送1w作为初始金额进行购物，所以对其的加密，后续支付必须要再次输入，否则无法进行购物。\n4. 本项目运用了gorm的读写分离，所以要保证mysql的数据一致性。\n5. 引入了ELK体系，可以通过docker-compose全部up起来，也可以本地跑(确保ES和Kibana都开启)\n6. 用户创建默认金额为 **1w** ，默认头像为 `static/imgs/avatar/avatar.jpg`\n# 如何导入并测试接口\n\n打开postman，点击导入\n\n![postman导入](doc/1.点击import导入.png)\n\n选择导入文件\n![选择导入接口文件](doc/2.选择文件.png)\n\n![导入](doc/3.导入.png)\n\n效果\n\n![展示](doc/4.效果.png)\n\n接下来点击Collection标题(gin-mall)\n在`Variables`中新增一个名为`url`的变量，Initial value和Current value均填入`localhost:5001/api/v1/`，然后保存，就可以开始测试了\n\n![创建环境变量](doc/6.postman创建环境变量.png)\n\n![创建环境变量](doc/7.创建url变量.png)\n\n\n这里是用postman查询es，Kibana也可以查看es！\n\n![postman-es](doc/5.postman-es.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCocaineCong%2Fgin-mall","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCocaineCong%2Fgin-mall","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCocaineCong%2Fgin-mall/lists"}