{"id":17991677,"url":"https://github.com/iyear/hduhelp-interview","last_synced_at":"2025-08-28T06:18:24.831Z","repository":{"id":64304031,"uuid":"411222340","full_name":"iyear/hduhelp-interview","owner":"iyear","description":"A Gin Web Project Template","archived":false,"fork":false,"pushed_at":"2021-10-27T12:47:45.000Z","size":96,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-23T22:25:46.846Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iyear.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-09-28T09:44:45.000Z","updated_at":"2022-09-10T02:33:39.000Z","dependencies_parsed_at":"2023-01-15T10:15:19.766Z","dependency_job_id":null,"html_url":"https://github.com/iyear/hduhelp-interview","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/iyear/hduhelp-interview","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iyear%2Fhduhelp-interview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iyear%2Fhduhelp-interview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iyear%2Fhduhelp-interview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iyear%2Fhduhelp-interview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iyear","download_url":"https://codeload.github.com/iyear/hduhelp-interview/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iyear%2Fhduhelp-interview/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272452879,"owners_count":24937467,"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","status":"online","status_checked_at":"2025-08-28T02:00:10.768Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2024-10-29T19:23:20.904Z","updated_at":"2025-08-28T06:18:24.801Z","avatar_url":"https://github.com/iyear.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 简介\n\n这个项目是面试杭电助手的任务，也是一个自己总结出来的 `Gin Web` 项目模板。\n\n面试任务在根目录下的 `task.md`\n\n以前一直没有用 `Go` 正经写过 `Web` 项目，趁这个机会把开发小型 `Web` 项目的整个流程学习一下，并总结自己的一套项目结构。\n\n## 文档\n### API\n```\n// \u003chost\u003e/doc/index.html\nswag init\n```\n### 前端获取AccessToken\n在登录回调成功后，后端会发起一个 `\u003chost\u003e/#/token=\u003cAccessToken\u003e` 的重定向\n   \n前端可在此阶段获取 `token` 并存于 `Cookie` 或 `LocalStorage`，并在每次请求时将 `token` 置于鉴权头中\n## 配置文件\n\n根目录下新建 `config.yml`\n\n第一次启动后需要在 `photos` 与 `departs` 表中手动添加 `id` 为 `-1` 的默认照片和默认部门\n\n```yaml\n# 监听端口\nport: 8080 \n# DEBUG Mode\n# 开启后将启用 Gin Logger,Gorm Logger,Swagger Doc\ndebug: true\n# 前端主页地址，末尾带/\nurl: https://baidu.com/\n# 对单客户端的每秒请求次数限制，根据接口、ip拦截，示例为限制两秒一次\nlimit: 0.5\nphoto:\n  # 图片上传大小范围，单位:KB\n  min: 50\n  max: 5120\n  # 图片MIME限制\n  mime:\n    - image/jpeg\n    - image/png\npath:\n  # 以 / 结尾\n  # 图片保存位置\n  photo: ./data/upload/\n  # 临时目录(暂时无用)\n  temp: ./data/tmp/\nmysql:\n  # mysql信息\n  host: 127.0.0.1\n  port: 3306\n  user: root\n  password: root\n  database: hduhelp\nauth:\n  # 杭电助手OAuth信息\n  client_id: xxxxxxxxx\n  client_secret: xxxxxxxxxxxxxxx\n  # 后端登录Callback地址\n  redirect_url: http://localhost:8080/auth\n```\n\n## 结构\n\u003cdetails\u003e\n\u003csummary\u003e项目结构\u003c/summary\u003e\n\n- project\n    - api (controller) 版本分离\n        - v1\n            - stu.go\n            - ...\n        - api.go  base resp,读参数和响应的处理函数\n        - auth.go 登录callback\n    - conf 配置及常量级的包\n        - e 错误码\n            - code.go\n            - msg.go\n        - app.go 主要配置\n        - conf.go 入口\n    - db 数据库\n        - db.go 入口\n        - mysql.go 初始化\n        - bolt.go 初始化\n        - ...\n    - middleware 中间件\n        - auth.go 鉴权\n        - ...\n    - model 模型和请求、响应结构体定义\n        - stu.go 学生\n        - photo.go 照片\n        - ...\n    - pkg 其他包\n        - oss\n        - ...\n    - router 路由\n        - router.go 路由配置\n    - server 服务器\n        - server.go 项目入口，初始化和启动服务\n    - service 服务\n        - srv_stu 学生\n            - stu.go 增删改查和与 controller 对接的函数\n        - srv_photo 照片\n            - photo.go\n        - ...\n    - util 工具类\n        - base.go 基础工具\n        - ...\n    - main.go 总入口\n\u003c/details\u003e\n\n-------\n\n补充：这个结构对于该项目粒度还是过细\n\n小型项目可以在 `service` 直接操作数据库\n\n大型项目可以增加 `protocol` 层用于协议转发，同时分离出 `db` 层\n\n## 技术点\n\n开发的过程中解决的一些问题和一些经验\n\n### 上传文件类型校验\n\n根据 https://github.com/gin-gonic/gin#single-file ，`FileName` 不可信，所以判断 `ContentType` 须通过文件头特征。\n\n### 中间件编写\n\n以前一直不敢写中间件，感觉高大上，这次看了官方的 `gin-contrib` 后发现简单的中间件还是很好写的，就是一个流程控制\n\n### Swagger文档\n\n因为这是一个正经的项目，终于试了试 `swagger-go` ，用着真舒服，直接可以在线调试，结构清晰\n\n### 不要用布尔型\n\n用 `int` 的 `1`和 `2` 代替布尔值，布尔值在参数校验和输出要特意关注忽略和默认值导致的误认为未传参，非常麻烦，血泪教训。\n\n### 不要用任何默认值代表实际意义\n\n\u003e 前段时间遇到过这种问题，某个参数是必填的，但是可选的值包括此类型值的零值，最后把这个类型的值设置为指针类型的方式解决的\n\n### .....\n\n## License\n\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiyear%2Fhduhelp-interview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiyear%2Fhduhelp-interview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiyear%2Fhduhelp-interview/lists"}