{"id":36870886,"url":"https://github.com/likakuli/generic-project-template","last_synced_at":"2026-01-12T15:01:21.948Z","repository":{"id":44874918,"uuid":"365140445","full_name":"likakuli/generic-project-template","owner":"likakuli","description":"通用restful api项目模板","archived":false,"fork":false,"pushed_at":"2021-05-12T22:51:23.000Z","size":27180,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-18T17:08:42.982Z","etag":null,"topics":["circuit-breaker","go","health-check","mock","pprof","prometheus-metrics","ratelimit","restful-api","testing","tracing"],"latest_commit_sha":null,"homepage":"https://www.likakuli.com/posts/generic-project-template/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/likakuli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-07T06:47:22.000Z","updated_at":"2022-07-12T09:48:48.000Z","dependencies_parsed_at":"2022-08-29T04:21:27.194Z","dependency_job_id":null,"html_url":"https://github.com/likakuli/generic-project-template","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/likakuli/generic-project-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likakuli%2Fgeneric-project-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likakuli%2Fgeneric-project-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likakuli%2Fgeneric-project-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likakuli%2Fgeneric-project-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/likakuli","download_url":"https://codeload.github.com/likakuli/generic-project-template/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/likakuli%2Fgeneric-project-template/sbom","scorecard":{"id":589648,"data":{"date":"2025-08-11","repo":{"name":"github.com/likakuli/generic-project-template","commit":"4af8f9e1b7bc063156723dcf82b5919fdf6554b6"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.8,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/17 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: containerImage not pinned by hash: docker/Dockerfile:1: pin your Docker image by updating mysql to mysql@sha256:a776e89aad2d425c248ccfb840115aaa52883499ff36512db4d503b11aae455a","Warn: goCommand not pinned by hash: vendor/github.com/json-iterator/go/build.sh:10","Warn: goCommand not pinned by hash: vendor/github.com/pelletier/go-toml/benchmark.sh:10","Warn: goCommand not pinned by hash: vendor/github.com/pelletier/go-toml/benchmark.sh:11","Warn: goCommand not pinned by hash: vendor/github.com/pelletier/go-toml/test.sh:26","Warn: goCommand not pinned by hash: vendor/github.com/pelletier/go-toml/test.sh:27","Warn: goCommand not pinned by hash: vendor/github.com/pelletier/go-toml/test.sh:28","Warn: goCommand not pinned by hash: vendor/github.com/pelletier/go-toml/test.sh:29","Info:   0 out of   1 containerImage dependencies pinned","Info:   3 out of  10 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":0,"reason":"19 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2021-0052 / GHSA-h395-qcrw-5vmq","Warn: Project is vulnerable to: GHSA-3vp4-m3rf-835h","Warn: Project is vulnerable to: GO-2023-1737 / GHSA-2c4m-59x9-fr2g","Warn: Project is vulnerable to: GO-2025-3372 / GHSA-6wxm-mpqj-6jpf","Warn: Project is vulnerable to: GO-2022-0322 / GHSA-cg3q-j54f-5p7p","Warn: Project is vulnerable to: GO-2022-0493 / GHSA-p782-xgp4-8hr8","Warn: Project is vulnerable to: GO-2021-0113 / GHSA-ppp9-7jff-5vj2","Warn: Project is vulnerable to: GO-2022-1059 / GHSA-69ch-w2m2-3vjp","Warn: Project is vulnerable to: GO-2020-0015 / GHSA-5rcv-m4m3-hfh7","Warn: Project is vulnerable to: GO-2021-0227 / GHSA-3vm4-22fp-5rfm","Warn: Project is vulnerable to: GO-2022-0968 / GHSA-gwc9-m7rh-j2ww","Warn: Project is vulnerable to: GO-2021-0356 / GHSA-8c26-wmh5-6g9v","Warn: Project is vulnerable to: GO-2024-2961","Warn: Project is vulnerable to: GO-2023-2402 / GHSA-45x7-px36-x8w8","Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77","Warn: Project is vulnerable to: GO-2020-0017 / GHSA-w73w-5m7g-f7qc","Warn: Project is vulnerable to: GO-2021-0053 / GHSA-c3h9-896r-86jm","Warn: Project is vulnerable to: GO-2020-0036 / GHSA-wxc4-f4m6-wwqv"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T21:31:08.071Z","repository_id":44874918,"created_at":"2025-08-20T21:31:08.071Z","updated_at":"2025-08-20T21:31:08.071Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28340415,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["circuit-breaker","go","health-check","mock","pprof","prometheus-metrics","ratelimit","restful-api","testing","tracing"],"created_at":"2026-01-12T15:01:13.244Z","updated_at":"2026-01-12T15:01:21.937Z","avatar_url":"https://github.com/likakuli.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.com/likakuli/generic-project-template.svg?branch=master)](https://travis-ci.com/likakuli/generic-project-template)\n## 通用Restful API项目模板\n\n欢迎使用，这是一个用Go编写的简单通用的Restful API项目，遵循SOLID原则。\n\n部分灵感来自于 [service-pattern-go](https://github.com/irahardianto/service-pattern-go)\n\n### 依赖\n\n* [Gin](https://github.com/gin-gonic/gin)\n* [Gorm](https://github.com/go-gorm/gorm)\n* [Testify (Test \u0026 Mock framework)](https://github.com/stretchr/testify)\n* [Mockery (Mock generator)](https://github.com/vektra/mockery)\n* [Hystrix-Go (Circuit Breaker)](https://github.com/afex/hystrix-go)\n\n### 开始\n\n* [安装](#安装)\n* [介绍](#介绍)\n* [目录结构](#目录结构)\n* [Mocking](#mocking)\n* [Tesing](#testing)\n* [能力支持](#能力支持)\n\n### 安装\n\n**克隆项目代码**\n\n```shell\ngit clone https://github.com/likakuli/generic-project-template.git\n```\n\n**启动mysql服务并初始化数据库**\n\n```shell\ndocker run --name=mysql -it -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d registry.cn-beijing.aliyuncs.com/likakuli/mysql\n```\n\n**注意**：如果是在MacOS上使用Docker for Mac启动的容器，则需要安装 [docker-connector](https://github.com/wenjunxiao/mac-docker-connector) ，否则无法在本机通过容器IP访问容器，原因参考[这里](https://docs.docker.com/docker-for-mac/networking/#there-is-no-docker0-bridge-on-macos)。安装命令如下\n\n```shell\n# 安装 docker-connector\nbrew install wenjunxiao/brew/docker-connector  \n# 把 docker 的所有 bridge 网络都添加到路由中\ndocker network ls --filter driver=bridge --format \"{{.ID}}\" | xargs docker network inspect --format \"route {{range .IPAM.Config}}{{.Subnet}}{{end}}\" \u003e\u003e /usr/local/etc/docker-connector.conf  \n# 启动服务\nsudo brew services start docker-connector  \n# 在 docker 端运行 wenjunxiao/mac-docker-connector，需要使用 host 网络，并且允许 NET_ADMIN\ndocker run -it -d --restart always --net host --cap-add NET_ADMIN --name connector wenjunxiao/mac-docker-connector\n```\n\n镜像涉及到的Dockerfile与sql放置在`docker`文件夹下\n\n**运行单元测试**\n\n```shell\nmake test\n```\n\n**编译程序**\n\n```shell\nmake build\n```\n\n**运行程序**\n\n```shell\n# 替换配置文件MySQL connectionString\n./docker/replace_ip.sh\n# 启动程序\n./generic-project-template --config=./conf/config.toml --log_dir=./logs --v=1\n```\n\n**访问程序**\n\n```shell\ncurl http://localhost:8080/api/v1/score/Lucy/vs/Lily\n```\n\n### 介绍\n\n这是一个简单通用的Restful API项目，内置依赖注入、Mocking等功能，旨在方便快速的编写安全可靠的Restful API代码。不同的数据结构之间通过接口来访问，避免直接引用具体的实现，这样就可以实现依赖注入及采用Mock结构进行单元测试的效果。\n\n举例来说：\n\n`IPlayerServie --\u003e IPlayerRepository`\n\n```go\ntype PlayerController struct {\n\tservice interfaces.IPlayerService\n}\n\ntype playerService struct {\n\trepo interfaces.IPlayerRepository\n}\n```\n### 目录结构\n\n```text\n/cmd\n  /- apiserver\n/conf\n/pkg\n  /- config\n  /- controllers\n  /- interfaces\n  /- models\n  /- repositories\n  /- server\n    /- middlewares\n    |- container.go\n    |- router.go\n    |- server.go\n  /- services\n  /- viewmodels\n```\n**controllers**\n\n控制器文件夹下包含所有`Gin Route Handler`，里面只包含处理`Request`和`Response`的逻辑，不包含任何业务逻辑和数据访问逻辑。仅依赖于`interfaces`下的`IService`接口，不依赖于具体实现。\n\n**interafces**\n\n接口文件夹下存放所有`IService`和`IRepository`接口定义及通过`Mockery`自动生成的用于单元测试的文件，不包含具体接口实现。\n\n**models**\n\n模型文件下下存放所有与数据库映射的实体模型对应的`Go Struct`，只包含数据结构，不包含数据访问逻辑。可以由 [gen](https://github.com/smallnest/gen) 根据数据库表结构自动生成，详情参考[这里](https://mp.weixin.qq.com/s/J7NO_kybMtatpWCnghu6Ag )\n\n**repositories**\n\n仓库文件夹下存放所有数据库访问逻辑，且实现了`interfaces`下定义的`IRepository`接口，主要用到`models`文件夹下定义的实体结构。\n\n**services**\n\n服务文件夹下存放所有实现了`services`下定义的`IService`接口的逻辑，供`controllers`直接使用。其中涉及到的数据库访问部分均通过调用`interfaces`下的`IRepository`接口实现，不依赖任何具体实现。\n\n**viewmodels**\n\n视图模型文件夹下存放所有需要与API交互的实体，主要包含从API获取到的结构和返回值的结构。与`models`的区别在于前者对应api层，后者对应数据库层。\n\n**router**\n\n路由文件夹下包含了所有可以对外提供服务的`Restful API`的路由注册逻辑。\n\n**container**\n\n容器文件下包含了所有依赖注入需要的`Provider`的逻辑，且在此选择具体使用的接口实现类型。\n\n### Mocking\n\n为方便进行单元测试，使用`Mockery`自动`interfaces`下接口实现，例如生成`IPlayerService的实现`，只需要进入`interfaces`文件夹下执行如下命令即可，最后会在`interfaces`下自动创建`mocks`文件夹来存放自动生成的文件。\n\n```shell\nmockery -name=IPlayerService\n```\n\n需要提前安装`mokery`工具\n\n### Testing\n\n有了依赖注入和`Mock`功能后，就可以针对任意接口实现编写单元测试了，示例中添加了针对`services`he`controllers`的单测，供参考。\n\n### 能力支持\n\n- [x] Tracing\n- [x] PProf\n- [x] Prometheus Metrics\n- [x] Health Check\n- [x] Mock\n- [x] Testing\n- [x] Circuit Breaker\n- [x] Rate Limit\n- [x] Common [go-utils](https://github.com/leopoldxx/go-utils)\n- [ ] ...\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flikakuli%2Fgeneric-project-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flikakuli%2Fgeneric-project-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flikakuli%2Fgeneric-project-template/lists"}