Skip to content

代码生成

fun 的生成器把注册的服务变成带完整类型的客户端代码:TS(前端)与 Go(服务间调用)可选。v1.3.2 起提供 BindServiceForGen——生成不依赖任何基础设施。

生成命令

推荐独立 cmd/gen(或放测试里):

go
// cmd/gen/main.go
package main

import (
    "fmt"

    "github.com/cyi-cc/fun"
    "hello-fun"
)

func main() {
    f := fun.New()
    // 只登记类型元信息,不装配任何基础设施——数据库/Redis 无需运行
    f.BindServiceForGen(&OrderSvc{})
    f.BindServiceForGen(&ChatSvc{})

    fun.SetOutput("./frontend/src/api") // 输出目录(默认 ./gen)
    fun.GenCode(fun.GenTs{})            // 加 fun.GenGo{} 同时生成 Go 客户端
    fmt.Println("done")
}
bash
go run ./cmd/gen

SetOutput 指向的目录会被清空

GenCode 执行时会 RemoveAll 整个输出目录再写入。务必指向专门的生成目录(如 frontend/src/api),不要指向源码根目录。

BindServiceForGen vs BindService

BindServiceBindServiceForGen
反射登记方法
装配依赖(拉起 Postgres/Redis 连接)❌ 不会
用于服务启动代码生成

BindService 做生成会把基础设施真正拉起来(New() 建连接)——生成命令请始终用 BindServiceForGen

产物结构

<out>/
├── ts/                          # GenTs 产物
│   ├── client.ts                # Client 类 + result<T> + 拦截器类型(零依赖)
│   ├── fun.ts                   # api.create(url) 聚合入口
│   ├── orderSvc.ts              # 每个有方法的服务一个文件(无方法的服务不生成)
│   ├── chatSvc.ts
│   ├── createOrderDto.ts        # DTO / 返回类型 interface
│   ├── orderDto.ts
│   └── orderStatus.ts           # 枚举(含 DisplayNames)
└── go/                          # GenGo 产物(可选)
    ├── fun.go
    ├── orderSvc.go
    └── ...
  • 产物固定落在 <out>/ts/(Go 在 <out>/go/)子目录;要拍平到目录根,生成后自行 os.Rename 上移一层;
  • 生成确定性:service / method / imports 全部按源端排序,重复生成字节一致,可安全进 CI / code review;
  • client.ts 自包含、零运行时依赖;JS 项目也可直接 import(Vite / esbuild 原生转译 .ts)。

聚合入口 fun.ts

ts
import { api } from './api/ts/fun'

const c = api.create('/api')   // url 会拼成 `${url}/cell`
c.orderSvc.create({ sku: 'A', count: 1 })

服务属性名首字母小写(orderSvc),方法名保持原样。用法详见下一章 TS 客户端使用

何时重新生成

服务定义(方法、DTO、枚举)一变就重新跑 go run ./cmd/gen。生成产物是纯派生代码——不要手改,改了也会被下次生成覆盖(输出目录整个清空)。

下一步

基于 MIT 许可发布