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
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() → 发送到客户端
优势
- 清晰的职责分离:Context只负责状态管理,Request负责读取,Response负责写入
- 灵活的协议支持:支持有帧头和无帧头协议
- 现代化的API:简洁、直观、类型安全
- 易于扩展:可以轻松添加新的协议和编解码器
- 类型安全:使用接口和泛型(Go 1.18+)保证类型安全