You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5.8 KiB

API设计文档

核心接口设计

1. Context上下文

type Context interface {
    context.Context
    
    // 获取Request和Response对象
    Request() request.Request
    Response() response.Response
    Connection() Connection
    
    // 状态管理
    Set(key string, value interface{})
    Get(key string) interface{}
    MustGet(key string) interface{}
}

2. Request请求

type Request interface {
    // Raw 获取原始数据(未解码的字节)
    Raw() []byte

    // Data 获取协议解码后的数据(去除帧头后的字节)
    Data() []byte

    // Decode 解码为Go对象经过protocol decode + codec decode
    Decode(v interface{}) error

    // DecodeWithCodec 使用指定的编解码器解码
    DecodeWithCodec(v interface{}, codecName string) error

    // Header 获取协议帧头(如果有)
    Header() FrameHeader

    // Protocol 获取协议信息
    Protocol() protocol.Protocol

    // ProtocolVersion 获取协议版本
    ProtocolVersion() string
}

3. Response响应

type Response interface {
    // Write 写入数据(自动编码)
    Write(data interface{}) error

    // WriteWithCodec 使用指定的编解码器写入数据
    WriteWithCodec(data interface{}, codecName string) error

    // WriteBytes 写入原始字节(绕过编码)
    WriteBytes(data []byte) error

    // WriteString 写入字符串
    WriteString(s string) error

    // SetHeader 设置协议帧头(如果有)
    SetHeader(header FrameHeader) error

    // Header 获取协议帧头
    Header() FrameHeader

    // Send 发送响应(如果使用缓冲模式)
    Send() error

    // Protocol 获取协议信息
    Protocol() protocol.Protocol
}

4. Protocol协议

type Protocol interface {
    // Name 获取协议名称
    Name() string

    // Version 获取协议版本
    Version() string

    // HasHeader 是否有帧头无帧头协议返回false
    HasHeader() bool

    // Encode 编码消息(添加帧头)
    Encode(data []byte, header FrameHeader) ([]byte, error)

    // Decode 解码消息(提取帧头和数据)
    Decode(data []byte) (FrameHeader, []byte, error)

    // Handle 处理消息(可选)
    Handle(ctx context.Context, data []byte) ([]byte, error)
}

5. FrameHeader协议帧头

type FrameHeader interface {
    // Get 获取帧头字段
    Get(key string) interface{}

    // Set 设置帧头字段
    Set(key string, value interface{})

    // Encode 编码为字节
    Encode() ([]byte, error)

    // Decode 从字节解码
    Decode(data []byte) error
}

使用示例

基本使用(有帧头协议)

func handler(ctx context.Context) error {
    req := ctx.Request()
    resp := ctx.Response()
    
    // 读取协议帧头
    header := req.Header()
    if header != nil {
        messageType := header.Get("message_type")
        // 使用帧头信息
    }
    
    // 读取数据(自动解码)
    var requestData MyRequest
    if err := req.Decode(&requestData); err != nil {
        return err
    }
    
    // 处理业务逻辑
    responseData := MyResponse{
        Code: 200,
        Data: "success",
    }
    
    // 设置响应帧头
    respHeader := resp.Header()
    if respHeader != nil {
        respHeader.Set("message_type", 0x01)
    }
    
    // 写入响应(自动编码)
    return resp.Write(responseData)
}

无帧头协议

func handler(ctx context.Context) error {
    req := ctx.Request()
    resp := ctx.Response()
    
    // 无帧头协议,直接读取原始数据
    rawData := req.Data()  // 或 req.Raw()
    
    // 处理数据
    result := processData(rawData)
    
    // 写入响应(协议会自动添加\n等分隔符
    return resp.WriteString(result)
}

指定编解码器

func handler(ctx context.Context) error {
    req := ctx.Request()
    resp := ctx.Response()
    
    // 使用指定的编解码器解码
    var data MyData
    if err := req.DecodeWithCodec(&data, "msgpack"); err != nil {
        return err
    }
    
    // 使用指定的编解码器编码
    return resp.WriteWithCodec(MyResponse{Code: 200}, "msgpack")
}

自定义协议帧头

func handler(ctx context.Context) error {
    req := ctx.Request()
    resp := ctx.Response()
    
    // 读取请求帧头
    reqHeader := req.Header()
    if reqHeader != nil {
        // 获取帧头字段
        msgType := reqHeader.Get("message_type")
        seqNum := reqHeader.Get("sequence")
        // ...
    }
    
    // 读取数据
    var data MyData
    req.Decode(&data)
    
    // 创建响应帧头
    respHeader := resp.Header()
    if respHeader != nil {
        respHeader.Set("message_type", 0x02)
        respHeader.Set("sequence", seqNum)
        respHeader.Set("status", 0)
    }
    
    // 写入响应
    return resp.Write(MyResponse{Code: 200})
}

数据流程

读数据流程

1. Connection.Read() → []byte (原始字节)
   ↓
2. Protocol.Decode() → FrameHeader + []byte (帧头 + 数据)
   ↓
3. Request.Data() → []byte (数据部分)
   ↓
4. Request.Decode() → interface{} (Go对象经过codec decode)

写数据流程

1. Response.Write(interface{}) → Go对象
   ↓
2. Codec.Encode() → []byte (序列化后的数据)
   ↓
3. Protocol.Encode() → []byte (添加帧头)
   ↓
4. Connection.Write() → 发送到客户端

优势

  1. 清晰的职责分离Context只负责状态管理Request负责读取Response负责写入
  2. 灵活的协议支持:支持有帧头和无帧头协议
  3. 现代化的API:简洁、直观、类型安全
  4. 易于扩展:可以轻松添加新的协议和编解码器
  5. 类型安全使用接口和泛型Go 1.18+)保证类型安全