# 4.6 目录结构设计 :::tip 概述 目录即架构:internal 对外不可见、utility 无业务语义、一模块四文件同名成套。本页解释"为什么这样分",目录树本身见 [1.3 项目目录结构](/zh/directory.html)。 ::: ## 顶层划分的逻辑 | 目录 | 定位 | 判定标准 | |---|---|---| | internal/ | 业务代码 | 含业务语义,Go 编译器层面禁止外部引用 | | utility/ | 基础设施 | 无业务语义,任何项目可复用 | | cmd/ | 可执行入口 | package main,只做装配不做逻辑 | | templates/ | 生成器模板 | 渲染产物是代码,非运行时依赖 | | config/ resource/ | 运行期数据 | 配置与静态资源 | | deploy/ | 交付物料 | Docker/Nginx,不参与编译 | | document/ | 项目文档 | 规约与 SQL 脚本 | | ui/ | 前端 | 独立工具链,独立生命周期 | ## internal 内部的分层逻辑 ```text model/ 数据形态的定义(dto 契约、db 连接、hooks 红线) router/ HTTP 装配(注册引擎 + 元数据) middleware/ 横切(每个文件一个关注点) handler/ 入口(最薄) service/ 业务(最厚) repository/ 数据访问(唯一 SQL 触点) task/ 后台(与请求链无关的定时逻辑) server/ 生命周期(启动与关闭) consts/ 跨层共享的常量 migrate/ 独立工具引擎(跨库迁移) ``` 依赖只能向下:repository 不 import service,service 不 import handler。 ## 一模块四文件的价值 同名的 `internal/{model/dto,repository,service,handler}/{module}.go`: - **可检索**:`example` 一个关键词命中全链路 - **可生成**:生成器按同名规则产出与覆盖 - **可审查**:PR 按模块聚合,四文件即一个完整变更单元 - **规约自明**:新模块不问即知放哪里 ## utility 的边界 utility 包禁止 import internal(基础设施不依赖业务)。内部互相引用仅限极底层(如 logger 被各包使用)。每个包一个关注点,13 个包与 config.yaml 配置节大体一一对应。 ## 运行期目录 | 目录 | 内容 | 处置 | |---|---|---| | log/ | zap 文件日志 | LogClean 任务按保留期清理 | | upload/ | 上传文件(temp + 正式子目录) | temp 按天清理;生产由 nginx 直供 | 两者都在 .gitignore,不进版本库。 ## 前后端的对称性 ```text 后端 RouteSpec Path: /api/example/page 前端 api 模块: ui/src/api/tool/example.ts → url: '/example/page' 后端菜单 component: tool/example/index 前端页面: ui/src/views/tool/example/index.vue ``` 五处路径同构——这是生成器能一键打通前后端的原因。 ## 下一步 → [4.7 基座与公共体系](/zh/architecture/base-system.html)