1. 为什么做 t3code代码资产的“废墟化”与三段式解决思路说实话最让我崩溃的不是复杂的业务逻辑而是每次新项目起步时那几十行重复到闭着眼都能敲出来的初始化代码。我手机里存了十几个“starter template”GitHub 上也 star 了一堆 boilerplate 仓库可真到用的时候不是目录结构太重就是依赖版本早就过时最后还是老老实实手动建目录、手写 main.go、手动接路由。t3code 就是在这种反复受挫之后被我一点点打磨出来的东西——一个本地优先、纯终端操作的代码生成与项目脚手架工具。它不依赖任何云端服务不强迫你登录账号核心就干一件事把“需求描述到项目骨架”的路径缩短成一条可复用的流水线。T3 这个名字不是随便起的。我刚画草图的时候整个工具被我拆成了三个阶段Translate、Template、Transpile。Translate 负责把输入的参数和描述解析成结构化配置Template 负责加载本地模板资产Transpile 负责把模板渲染成真实代码并落盘。三个单词都以 T 开头于是就叫 t3code。这个名字也暗示了它的设计哲学别把代码生成当成一个黑盒它本质上就是一个带管道的文本加工过程每一层都可以被检查、被调试、被替换。这个工具适合谁我觉得主要是这几类人经常要起新服务的后端开发者、需要批量生成微服务骨架的小团队、以及像我一样喜欢把常用代码片段沉淀成个人资产的前端或全栈工程师。它不解决业务逻辑问题也不替你写核心算法它解决的是“每次开新项目都要重来一遍”这种体力活。如果你也有同样的痛点接下来这几千字应该能帮你快速判断它值不值得用以及怎么把它接到自己的工作流里。1.1 先看一个每天都在重复的场景假设你今天要写一个内部用的用户查询服务。正常流程大概是打开终端mkdir user-servicecd进去然后开始go mod init、建cmd/server/main.go、拉两个依赖、配日志、配配置读取、写健康检查接口……这些动作单独看都不难但加起来至少浪费二十到三十分钟。更烦的是一个月后你又要写一个订单服务流程一模一样只是名字换了。如果只是时间成本也就算了真正的隐患在于复制粘贴。我见过很多项目里留着上一个服务的类名、日志前缀甚至是错误提示里的项目名就是因为脚手架是手动复制的改漏了某个地方。t3code 想做的事情很简单所有需要个性化的内容都通过变量注入生成时一次性替换干净从源头上杜绝“复制粘贴改漏”这种低级又致命的问题。1.2 T3 这三个阶段到底在说什么先解释一下每个 T 的实际含义因为后面所有操作都会围绕这三层展开。Translate 层处理的是输入。你可以在命令行里直接传参比如t3 gen go-api --name user-service --port 8080也可以把一段需求描述交给它例如“创建一个 REST 风格的 user service监听 8080 端口”。t3code 内置了一个非常轻量的关键词解析器会把描述拆成结构化参数。这个解析器不需要联网不认识复杂语义但它能稳定识别rest、api、portxxx这类高频词剩下的全部交给显式参数来兜底。我的建议是自然语言模式最多用来偷个懒正经用还是推荐写清楚--name这类参数可预测性更高。Template 层就是模板资产管理器。它会在~/.t3code/templates/下维护一个模板目录每个模板对应一个子文件夹。比如go-api里面放着template.yaml描述这个模板需要哪些变量和一堆源文件模板。这些模板文件大部分是普通代码文件只有带.tpl后缀的会被当作可渲染模板处理普通文件则直接复制避免无关内容被误改。Transpile 层是最终落地环节。它把 Translate 得到的参数和 Template 里的文件做渲染然后根据冲突策略写入目标目录。整个过程是一个清晰的管道每一层都有输入输出出了问题可以单独调试。这也是我在设计时最坚持的一点不做那种一键生成但看不到中间过程的黑盒。1.3 t3code 的重点不是生成而是“复用”很多人一听代码生成工具就会想到“低代码平台”或“AI 写码”。t3code 跟这些有个本质区别它默认你是一个会写代码、也愿意写代码的人。它不尝试替你写业务它只是帮你在需要重复的地方少做无用功。打个比方t3code 更像是你厨房里的调味料收纳架而不是自动炒菜机。自动炒菜机试图替代你做饭的决策权收纳架则只是帮你在做菜时快速拿到想要的东西。模板本身还是你根据自己的最佳实践写出来的所以项目里的代码风格、目录规范、依赖选型完全由你控制。用一段时间之后你会发现模板库本身就是一份活的知识沉淀——你踩过的坑、总结出的架构约定都固化在模板里了。新人入职拉一下模板仓库起一个项目就能看到团队的标准布局这比看十页文档都直观。2. 核心架构拆解t3code 的三级流水线是如何跑起来的上一节提到的 T3 三层不是概念空转而是对应着真实代码里的三条处理路径。这一节我按数据流向把每一层的实现思路和设计原因展开方便你在使用时理解它的行为也方便你将来在踩到边缘情况时知道该去哪里排查。2.1 Translate把“人话需求”转成结构化参数Translate 的输入有两种。第一种最常用是命令行参数。t3code 的命令格式类似t3 gen template-name --key value所有--key都会原样收集到一个 map 里。这里比较重要的是参数命名模板里声明变量名是ServiceName命令行参数会自动把 kebab-case 转为 PascalCase也就是说--service-name user-service会被转成ServiceNameuser-service。这个转换规则是固定的所以即使你记不住模板里的确切变量名只要按自然拼写传递参数基本不会错。第二种输入是自然语言描述我加了一个非常克制的解析器。比如你输入t3 gen go-api user service with port 8080解析器会做几件事先搜索service这个词作为服务名的兜底如果前面有名词就把那个词当作名字原型再查找port字段后面的数字会被提取出来。因为实现很简单解析失败时它会原样把整段描述塞给Description变量并打出一条警告提醒你改用显式参数。为什么不直接上一个优秀的大语言模型接口来解析因为我不想让一个本地脚手架工具依赖云端 API也不想引入额外的密钥和网络开销。模板生成的性质决定了输入格式通常都比较固定用规则解析的准确率已经足够还附带可离线运行、可离线测试的好处。如果你有更复杂的解析需求可以通过配置文件外挂自己的解析脚本t3code 只负责在渲染前把外部脚本的 stdout 接收为标准参数。2.2 Template模板目录规范与解析优先级模板目录被设计成一个标准文件树结构。下面是一个go-api模板的目录示例~/.t3code/templates/ └── go-api/ ├── template.yaml ├── cmd/ │ └── server/ │ └── main.go.tpl ├── internal/ │ └── config/ │ └── config.go ├── .gitignore └── README.md.tpltemplate.yaml是这个模板的身份证里面声明了模板名、描述、需要的变量以及校验规则。没有这个文件的目录也可以作为模板使用此时 t3code 会扫描目录内所有.tpl文件自动提取{{ .VarName }}这种占位符作为可填变量并给出一个通用模板描述。这种“零标记”模式适合快速测试但正式维护我还是建议写template.yaml因为变量的顺序、默认值和校验规则都是可读的文档。解析优先级是我反复调整过的一块。最终实现的顺序是模板自身template.yaml里的变量声明 → 项目级.t3code.yaml里的变量覆盖 → 全局配置~/.config/t3code/config.yaml里的公共变量 → 用户刚传入的命令行参数。听起来有点绕其实规则很简单作用域越小越优先。命令行参数是最具体的所以排在最后覆盖所有层级的同名变量。2.3 Transpile渲染、落盘与冲突处理Transpile 层做三件事递归遍历模板目录、渲染和复制文件、处理目标目录冲突。在递归遍历时扩展名为.tpl的文件会被送入渲染引擎t3code 底层用的是 Go 标准库的text/template实现然后做了一层函数扩充。渲染后的内容默认写到同名但去掉.tpl后缀的目标文件里比如main.go.tpl会变成目标目录的main.go。其他文件如.gitignore、静态资源等保持原样复制。文件名本身也可以含有模板占位符例如{{ .TableName }}.sql.tpl会被渲染成users.sql这在生成数据库迁移文件时特别有用。冲突处理是我很早就想明白要保守的地方。每次写入前如果目标文件已经存在t3code 不会静默覆盖而是按照下面的策略选择交互式终端会弹出提示让你选覆盖、跳过或保留两者非交互环境下默认跳过已存在的文件避免自动化脚本误伤。另外开启--backup后被覆盖的文件会先被移动到目标目录下的.t3code-backup-timestamp/文件夹后悔了随时可以翻出来。这条保命设计后面在踩坑章节我会单独细讲。2.4 上下文配置.t3code.yaml的加载顺序项目级的.t3code.yaml是使用中一定会碰到的文件它定义了生成内容的“上下文”。下面是一个最小示例# .t3code.yaml template: name: go-api output_dir: . vars: Owner: dev-team License: MIT hooks: after_generate: - gofmt -w .template.name指定默认使用的模板这样在项目内直接跑t3 gen就不必再带模板名vars里存放一些公共变量比如Owner和License今后生成任何子项目都会带上这些信息hooks.after_generate是在文件落地后要执行的命令通常用来做格式化。加载顺序上t3code 会先读全局配置再读当前目录的.t3code.yaml然后合并命令行参数。配置文件负责兜底命令行负责精确覆盖两者职责分明。3. 从零跑起来安装、初始化与第一次生成理论部分讲完下面进入实操。这一节的目标很简单把 t3code 装好初始化模板仓库成功生成一个 Go API 服务并能跑起来。整个过程大概十分钟跟着敲命令就行。3.1 安装与环境准备我用 Go 写了这个工具所以最直接的安装方式是用go installgo install github.com/t3code/cli/cmd/t3latest前提是本地已经装有 Go 1.21 或更高版本。装完后二进制会出现在$HOME/go/bin/t3Windows 是%USERPROFILE%\go\bin\t3.exe。如果你的PATH里还没有go/bin需要手动加一下。macOS 和 Linux 在.bashrc或.zshrc里加一行export PATH$HOME/go/bin:$PATHWindows 用户在 PowerShell 里推荐用$env:PATH $env:USERPROFILE\go\bin;$env:PATH先验证再通过系统设置里的环境变量面板做永久修改。加完 PATH 后执行t3 --version看到版本号就说明安装成功了。这一步看着简单但很多人卡在“装完找不到命令”其实不是没装上就是 Go 的 bin 目录没进 PATH。3.2 初始化自己的模板仓库t3code 默认的模板目录是~/.t3code/templates但这个目录一般不会凭空出现所以要先用初始化命令创建t3 init执行后工具会创建模板目录、全局配置文件并放一个hello-world示例模板进去。你可以打开~/.t3code/templates/hello-world/看看结构里面有一个template.yaml、一个hello.txt.tpl。这算是最小的可运行示例。我自己会把init理解成“创建你的代码资产保险柜”它不产生业务代码只负责把存放模板的架子打起来。如果你之前已经有一套自己的项目模板比如本地某个目录里躺着一个go-api-skeleton文件夹想把它纳入 t3code 管理只需要把它复制到~/.t3code/templates/下面并在里面补一个template.yaml文件。这一点比较灵活不需要你从零开始为 t3code 重新设计模板。3.3 生成第一个 Go API 服务完整命令与产物结构现在演示一个正式一点的例子。假设你要生成一个叫user-service的 Go API 项目监听在8080端口t3 gen go-api --name user-service --port 8080如果你在前面初始化时没有go-api这个模板也没有关系——先去仓库里找一个包含 Go API 骨架的模板放到本地或者用示例模板走一遍流程也行。关键是观察这次生成发生了什么。命令执行完后当前目录下会出现这样一个结构基于我维护的 go-api 模板user-service/ ├── go.mod ├── cmd/ │ └── server/ │ └── main.go ├── internal/ │ └── config/ │ └── config.go ├── .gitignore └── README.md注意main.go是从main.go.tpl渲染出来的里面已经带上了你传入的服务名和端口号。如果你打开文件不会看到任何残留的{{ .Name }}占位符这就是渲染已经成功的意思。我一般接着就跑一次cd user-service go mod tidy go run ./cmd/server能正常启动、健康检查接口能返回ok就算整条链路通了。3.4 第一次跑通后的检查清单我在最初使用这类工具时吃过亏后来总结了一份检查清单每次生成完都会扫一眼渲染完整性用grep或编辑器全局搜索目标目录里有没有残留的{{或}}。有就说明模板变量没有全部命中通常是变量名大小写对不上。目录位置确认生成的目标目录是当前工作目录还是配置里指定的output_dir否则文件容易散落到预料之外的地方。依赖可用性生成完毕不代表能编译过。跑一次go build或npm install确认模板里的依赖版本没有被锁定到一个已经不存在的版本。版本控制如果目标目录是一个已有 Git 仓库确认生成过程没有意外覆盖掉.git目录下的文件。正常情况下 t3code 不处理.git但你需要在模板目录里做同样的排除。这份清单花不了三十秒但能挡掉大部分因为模板过时引发的连环错误。4. 模板编写实战从一个 REST API 例子讲透变量注入工具的可用性最终取决于模板质量。一个设计良好的模板能让生成结果直接用一个偷懒的模板生成完还得手改一堆地方最后可能还不如不生成。这一节围绕一个 REST API 模板来拆解完整的变量注入方式你照着这套思路去写自己的模板基本不会踩大坑。4.1 模板目录里都该放什么我把模板目录分成三块声明文件、模板文件、静态文件。声明文件就是template.yaml它告诉工具“这个模板怎么用”模板文件是带有.tpl后缀的动态文件里面的占位符会被替换静态文件则完全不对内容做任何处理适合保存go.mod、.gitignore、资源文件这种很少需要个性化的内容。为什么要把静态文件和模板文件分开主要是为了安全和效率。安全在于像.gitignore这种文件里如果出现了{{字符被模板引擎强行解析反而容易报错效率在于静态文件直接复制零开销模板文件才需要走渲染管道。所以我的习惯是“能不模板化就不模板化”只有需要注入变量的节点才把文件后缀改成.tpl。4.2 变量声明、默认值与校验规则template.yaml的写法决定了用户使用这个模板时的体验。先看一个实用的例子# ~/.t3code/templates/go-api/template.yaml name: go-api description: Go REST API service skeleton version: 1.2.0 params: - name: ServiceName required: true help: Service name, e.g. user-service - name: Port default: 8080 validate: ^[0-9]{2,5}$ - name: ModulePath default: example.com/{{ .ServiceName }} help: Go module path每个变量可以设置required、default、validate和help。validate是一段正则表达式校验不通过时会提示用户重新输入这样可以尽早发现异常而不是等生成完才发现问题。default字段支持引用其他变量比如ModulePath的默认值用到了{{ .ServiceName }}渲染时会先解析依赖关系。这一层声明越完整命令行交互时体验就越顺滑因为它会根据help提示用户补充缺失的必填字段。我建议至少在template.yaml里维护好三样变量的中文或英文说明、是否需要必填、以及可能的默认值。很多用户第一次打开命令行工具会不知所措help文案能降低上手门槛。4.3 模板语法Go template 的常用管道与条件渲染t3code 的模板语法沿用了 Go 标准库text/template所以写过 Helm Chart 或 Kubernetes YAML 的人会特别熟悉。下面展示一个main.go.tpl的片段它演示了最常见的三种操作变量替换、自定义函数管道、条件分支。// main.go.tpl package main import ( fmt log net/http {{ .ModulePath }}/internal/config ) func main() { cfg : config.Load() http.HandleFunc(/healthz, func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, ok) }) addr : 127.0.0.1:{{ .Port }} log.Printf({{ .ServiceName | upper }} listening on %s, addr) if err : http.ListenAndServe(addr, nil); err ! nil { log.Fatal(err) } }渲染时如果把ServiceName设为user-service、Port设为8080、ModulePath设为example.com/user-service产物里{{ .ServiceName | upper }}就会变成USER-SERVICE。这里upper是 t3code 预置的自定义函数之一。目前内置了upper、lower、title、camel、snake、kebab等常用字符串转换函数基本覆盖了服务命名、类名生成、文件名拼接这些场景。条件渲染也很简单。比如想根据用户的开关生成不同内容{{ if .WithDocker }} FROM golang:1.22-alpine {{ else }} // Dockerfile skipped {{ end }}注意WithDocker需要在template.yaml里声明成一个布尔变量否则模板引擎拿不到类型信息条件判断就会出问题。4.4 用条件文件与子模板组装大项目一次性生成十几个文件的大型模板如果所有逻辑都塞在.tpl文件里会很难维护。我常用的做法有两个。第一个是“条件文件”在template.yaml里对一个文件声明when条件只有条件满足时才生成它。比如files: - path: deploy/Dockerfile when: {{ .WithDocker }}这种方式比在文件内部写if更适合控制整个文件是否存在。文件内容保持干净可读性也更高。第二个是“子模板”把一些重复出现的片段抽出来用{{ template header . }}嵌入到多个模板文件里。子模板通常放在模板目录下的_partials/子目录中t3code 会识别它但不直接生成文件只在被引用时渲染。这种组装方式特别适合生成微服务项目公共的header、logger、error-handler片段都复用同一份改一处所有服务模板同步更新。5. 踩坑实录流水线从原理到落地最容易翻车的四个位置再顺的工具真实使用中也不可能一次通过。我在做 t3code 以及用别的脚手架工具的过程中积累了不少“说多了都是泪”的经验。这一节是踩坑排查链路不是简单的错误答案对照表。5.1 Windows 路径分隔符一个反斜杠引发的渲染错位在 Windows 上跑 t3code 的用户最早遇到的一类问题是生成的文件里出现了奇怪的路径比如internal\config\config.go中的\c变成了某种特殊序列或模板变量里的 Windows 路径被错误转义。排查链路是这样的我先把报错文件里的异常内容输出来发现{{ .OutputDir }}渲染后是C:\Users\name\project但落盘时工具内部把它当成了字符串进行模板处理\U在某些渲染路径下会被转义成不可见字符。根因是模板引擎对反斜杠有特殊解释它不关心你是不是 Windows 路径。修复方案分两层。工具层面所有从参数和配置进入渲染上下文的字符串在 Windows 上都会预先将\统一替换为/等落盘写到实际文件系统时再由系统层恢复成合适的分隔符。模板编写者层面我建议不要在模板里直接拼接 Windows 路径而是传入相对路径用内置的path函数处理。现在我在 Windows 上跑模板之前会先跑一次t3 gen --dry-run --debug --output to stdout专门检查路径渲染是否正确。5.2 “变量不存在”的假报错先看上下文 JSON另一个高频报错是模板解析时出现map has no entry for key ServiceName。第一次遇到时我第一反应是模板变量名写错了仔细检查又发现拼写无误。后来才定位到真正原因模板里使用的是{{ .ServiceName }}而template.yaml里声明的变量名是serviceName。大小写不匹配模板引擎严格按名字查 map查不到就直接报错。这种问题其实很好排查但前提是你要能看见渲染上下文里到底有哪些键。t3code 提供了一个--debug模式执行命令时会先把最终合并好的参数以 JSON 格式打印出来然后才进入渲染阶段。我排查此类问题的习惯是先跑t3 gen go-api --name user-service --debug 2 ctx.json然后把ctx.json里vars区块的键名和模板里{{ .Xxx }}的变量做一次逐字比对。大部分“变量不存在”的报错都是大小写或前缀拼写问题打开 JSON 一眼就能看到。这里也提醒模板编写者变量名尽量统一风格。我的规范是全用 PascalCase比如ServiceName、ModulePath避免出现service_name、serviceName、ServiceName混用的情况。统一风格后命令行参数的 kebab-case 转换规则也能稳定工作。5.3 覆盖生成时的误删风险我为此加了保险这算是我最痛的教训之一。早期版本里如果目标目录不是空的t3code 会直接清空再写入理由是“生成前确保目录干净”。结果有一次我在项目根目录执行生成命令忘了指定子目录工具二话不说把整个项目目录清掉了。虽然那次有 Git 在手但丢失的未提交代码找不回来的恐惧感至今记忆犹新。从那次以后我把冲突策略全部改成了保守模式目标目录存在同名文件时默认跳过而不是覆盖必须覆盖时先往.t3code-backup-timestamp/里移动一份命令行交互模式下会弹出三种选择overwrite、skip、backup。我也强烈建议所有用户养成的习惯是每次生成前先跑t3 gen template --dry-run --diff这个命令不会写任何文件只会打印每个文件的“将创建/将更新/将跳过”状态。你可以把它理解成git diff --stat的预演版危险操作之前多花十秒钟看结果能省下难以估量的恢复成本。5.4 UTF-8 BOM 与中文注释渲染错乱最后说一个跟中文用户关系最大的坑。在 Windows 上用记事本保存过模板文件的读者应该知道记事本默认会在文本开头加一个 BOM 头。BOM 在大多数编辑器里不可见但字节序列确实存在。当这样的模板文件进入渲染流程后BOM 会被当成内容的一部分写到生成文件里轻则编译报错重则生成的文件开头出现一个幽灵字符排查起来特别恶心。解决思路也分两步。工具层面t3code 在读取模板文件时如果检测到 UTF-8 BOM会自动剥掉再进入渲染器从源头消灭问题。但我没办法保证所有使用者都更新到最新版本所以更稳的办法是模板文件一律用 UTF-8 无 BOM 编码保存并且可以在 Git 仓库里加一个.gitattributes文件强制统一换行符和编码* textauto eollf *.tpl text utf-8把模板仓库当成代码仓库来管理编码规范也是代码规范的一部分。这一条对团队协作尤其重要Windows 和 macOS 开发者容易在不知不觉间让编码差异渗透进生成的代码。6. 进阶玩法把 t3code 嵌进团队与自动化流程当 t3code 从“个人玩具”变成“团队基建”之后很多新的需求会浮出来模板怎么同步生成后能不能自动格式化测试环境里能不能跑生成命令这些场景我都实际摸索过下面挑几个最实用的展开说。6.1 模板仓库放进 Git一键同步到全队t3code 的模板目录本质上就是一堆普通文件天然适合放到 Git 仓库里管理。我的做法是建一个t3code-templates私有仓库里面放所有团队标准模板然后把本地~/.t3code/templates软链到仓库目录ln -s ~/workspace/t3code-templates ~/.t3code/templates这样每次提交代码后同事只需要git pull就能拿到最新模板。为了避免有人忘拉更新导致生成风格不统一我还在仓库里放了一个sync.sh脚本里面就两行git pull和t3 template verify --all。后者会遍历所有本地模板校验template.yaml格式、变量引用是否合理提前暴露坏模板。这种“模板即代码”的理念一旦跑起来团队代码风格统一就不是靠文档约束而是靠工具强制。新人加入项目组不需要消化一本厚厚的开发规范手册直接跑t3 gen就能得到符合约定结构的项目骨架。6.2 生成后自动格式化与测试模板生成出来的代码最常见的问题是格式不一致。不同模板编写者的习惯不同有的人缩进用空格有的人用 Tab有的人喜欢在导入声明里分组有的人不分。依靠人肉处理太累了而且大家转头就忘。t3code 的hooks.after_generate配置在这一步非常有用。你可以在.t3code.yaml里这样写hooks: after_generate: - gofmt -w . - prettier --write . - go test ./...生成完成、文件落盘之后t3code 会依次执行这些命令。如果某一步失败比如测试没过它会打印非零退出码并提醒你检查。我曾经用它把go test ./...也挂到生成链路里等于每一次脚手架初始化都是一次健康检查生成的服务至少是能通过 smoke test 的。这个习惯帮我挡掉过好几次模板依赖升级后引入的编译错误。要注意的是after_generate钩子默认只保证在当前输出目录执行不要在里面写cd这种命令最好让每个子命令本身就固定作用在当前目录。这样更安全也更容易在 CI 里复用。6.3 用 Docker 包一层模板隔离更省心有时候模板依赖的生成工具很重比如依赖特定版本的 Node.js、Java 工具链或者数据库客户端。如果团队成员本地没有配好这些环境跑t3 gen一样会失败。这种情况下我会用 Docker 把 t3code 和模板一起封装起来。以下是一个简单的Dockerfile示例FROM golang:1.22-alpine RUN apk add git \ go install github.com/t3code/cli/cmd/t3latest WORKDIR /workdir COPY templates /root/.t3code/templates ENTRYPOINT [t3]构建好后团队成员可以通过容器生成项目docker run --rm -v $PWD:/workdir myteam/t3code \ gen go-api --name user-service --port 8080这种封装方式把工具链的差异挡在容器外面宿主机的环境再乱也不影响生成结果。我在 CI 脚本里也用同样的方式跑批量生成测试先渲染一批测试项目再统一跑编译和 lint确保模板每次改动都不会破坏生成效果。6.4 我现在的使用习惯用了一段时间之后t3code 已经成了我启动任何新项目的默认动作。我现在本地维护着二十来个模板Go API、Python CLI、前端组件、数据处理脚本、数据库迁移模板还有几个用来生成内部工具的空项目骨架。每个模板都不大但都带着我在真实项目里验证过的默认配置比如日志格式、错误处理策略、测试框架选型。我给自己定了一个小规则每完成一个包含重复模式的功能就花十分钟把它提炼成模板或模板片段。比如上周我连续写了三个批处理脚本它们的参数解析和日志逻辑几乎一样我意识到这应该是下一个模板写完之后再碰到类似任务基本只需要填核心业务逻辑。这个习惯不仅减少了重复劳动还变相逼着我把自己的代码习惯整理得更清晰。模板库就像一面镜子它让你看到自己到底有多少“看似不同实则相同”的工作。如果你打算上手我建议从小模板开始不要一上来就做一个包罗万象的企业级脚手架。先选一个你每周都会写的项目类型写一个能生成最小可用结构的模板跑通一轮“生成—修改—使用—改进模板”的循环再慢慢加内容。工具不怕简单怕的是第一次用的时候就被自己的模板复杂度劝退。
阅读完成 · 觉得有帮助?