常见问题
按「现象 → 原因 → 解法」组织的高频踩坑清单。
注册期 panic
Unsupported types int
DTO 字段用了非法类型:普通 int / uint、float、map、any、匿名结构体、私有字段。
type BadDto struct {
Count int // ❌ panic
Count int64 // ✅ 定宽整型
Price float64 // ❌ panic
Price *string // ✅ 小数用字符串传
Meta map[string]string // ❌ panic
}完整规则见 DTO 与类型规则。
method X has more than one parameter / parameter must be a struct
方法参数超过 1 个,或参数不是 struct。多参数合并成一个 DTO:
func (s *Svc) List(page, size int) ... // ❌
func (s *Svc) List(dto ListDto) ... // ✅运行期错误
must be a pointer or have a corresponding field
非指针、非 slice 的 DTO 字段在请求里漏传或传了 null。可空字段改用 *T:
type Dto struct {
Name string // 必传——漏了就报这个错
Note *string // 可空
}客户端报 method not found
方法名首字母小写(未导出),不会被注册为端点。改成大写开头。
方法没被生成进 TS 客户端
同上——未导出方法不是端点;另外无方法的服务不生成文件。
前端联调
前端取不到字段 / 字段是 undefined
响应所有键已递归转首字母小写:SiteName → siteName,按 camelCase 取。TS 产物已按此生成,手写类型才会踩。
跨域失败(CORS error)
- 开发期:走 vite 代理(同源,无跨域);
- 直连:服务端
f.CORS(origin)加白名单,Origin 必须完全匹配(协议 + 域名 + 端口)。
404 / 405
- 路径不对:业务端点是
POST /cell,代理记得 rewrite 前缀(/api/cell→/cell); - 非 POST 打
/cell→ 405;未注册路径 → 404。
收到 Unexpected HTML response
网关 / 反代返回了 HTML(拦截页、错误页、502 页)。客户端已归一为 status=1 并附带 HTML 摘要,检查网关配置。
流式
客户端一直等,流不结束
业务 goroutine 忘了 st.Close()——零消息流也要 Close。见流式响应。
连接断开后 goroutine 泄漏
Send 在连接断开后返回 error,循环里必须检查并 return:
if err := st.Send(chunk); err != nil {
return // 连接已断,别再推了
}流被中间设备静默掐断(挂起无错误)
v1.3.6 起服务端每 25s 发空行心跳防掐断;客户端配 idleTimeoutMs 看门狗 + retry 重连。注意服务端 SetTimeouts 的 idle 要大于 25s。
长连接触发服务端 idle 超时断开
SetTimeouts 的 idle 配置过小,空闲流被 fasthttp 断开。调大 idle(> 25s 心跳间隔)。
代码生成
生成命令把数据库连上了 / 需要数据库在运行
用了 BindService 做生成。改用 BindServiceForGen——只登记元信息不装配。见代码生成。
生成把我的目录清空了
GenCode 会 RemoveAll 整个 SetOutput 目录。SetOutput 必须指向专门的生成目录,不能指源码根目录。
生成产物没拍平,多了一层 ts/ 目录
产物固定落在 <out>/ts/,生成后自行 os.Rename 上移一层。
错误处理
前端拿不到错误码
业务错误用 fun.Error(code, msg) 返回;普通 errors.New 会归为 status=1、无 code。
客户端 msg 和服务端日志对不上
框架错误刻意脱敏:客户端只收固定提示,完整细节在服务端 ErrorLogger。这是安全设计,不是 bug。
依赖注入
Wired 返回 error
装配失败:fun:"auto" 字段的依赖无法构造等。看错误信息定位到具体类型;New() 签名必须无参无返回。
服务里放了共享状态
服务实例每请求新建,状态不保留。共享资源放 Box(Wired 单例)里经字段注入。