Skip to content

线协议与错误处理

fun 的线协议极简:一种请求、一种响应。理解 Resultstatus 语义,前后端的错误处理就全部掌握了。

请求格式

所有业务请求都是 POST /cell,JSON body:

json
{
  "serviceName": "OrderSvc",
  "methodName": "create",
  "data": { "sku": "A-001", "count": 2 },
  "state": { "token": "eyJhbGci..." }
}
字段说明
serviceName / methodName端点定位,首字母大小写不敏感
dataDTO 参数,字段名大小写不敏感
state字符串字典,往返透传(token、请求标识等),可省略

/cell 路径返回 404,非 POST 返回 405。

响应格式:Result

go
// Go 侧定义
type Result[T any] struct {
    Code   *uint16 `json:"code,omitempty"`
    Data   *T      `json:"data,omitempty"`
    Msg    *string `json:"msg,omitempty"`
    Status uint8   `json:"status"`
}

TS 客户端里的形状:

ts
export type result<T> = {
  code?: number
  data?: T
  msg?: string
  status: number
}
  • data 为 nil 时整个字段省略;空 slice 输出 [] 而非 null
  • 所有对象键递归转首字母小写,前端按 camelCase 取值。

status 语义

status含义谁产生
0成功服务端
1框架 / 协议 / 基础设施失败(DTO 校验失败、JSON 非法、panic 兜底)服务端
2业务失败(fun.Error(code, msg) 构造)服务端
4外部请求失败或调用方取消(网络错误、HTTP 非 2xx、abort)TS 客户端
5明确的外部超时失败(AbortSignal.timeout 触发等)TS 客户端

4 / 5 只存在于客户端归一化结果里(请求没到达业务层),服务端永远不会返回它们。

业务错误:fun.Error

go
func (s *OrderSvc) Cancel(dto CancelDto) error {
    if dto.Reason == nil {
        return fun.Error(4004, "必须填写取消原因") // status=2
    }
    return nil
}

fun.Error(code, msg) 构造的错误,code / msg 原样透传给客户端:

json
{ "code": 4004, "msg": "必须填写取消原因", "status": 2 }

普通 error(如 fmt.Errorf / errors.New)会归为 status=1,msg 为错误文本——要带错误码给前端时必须用 fun.Error

框架错误的脱敏

DTO 解码失败、内部 panic 等框架级错误走 internalError 路径:

  • 客户端只收到固定提示(不含 JSON 解析细节、Go 类型名等内部信息);
  • 完整错误记入服务端日志(ErrorLogger)。

TIP

排障时先看服务端日志再对照客户端收到的 msg——两者详细程度不同是刻意设计。

完整往返示例

bash
# 成功
curl -X POST localhost:8080/cell -d \
  '{"serviceName":"OrderSvc","methodName":"get","data":{"Id":1}}'
# → {"status":0,"data":{"id":1,"status":1,"amount":"0.01"}}

# 业务错误
curl -X POST localhost:8080/cell -d \
  '{"serviceName":"OrderSvc","methodName":"cancel","data":{"Id":1}}'
# → {"code":4004,"msg":"必须填写取消原因","status":2}

# DTO 校验失败(非指针字段漏传)
curl -X POST localhost:8080/cell -d \
  '{"serviceName":"OrderSvc","methodName":"get","data":{}}'
# → {"msg":"...must be a pointer or have a corresponding field...","status":1}

流式响应

流式方法的响应不是 Result:Content-Type: application/x-ndjson,每行一个 JSON(键同样转小写)。首条消息 + 后续流的签名里,T 作为第一条消息下发。详见流式响应

下一步

基于 MIT 许可发布