# 架构重新设计 - 问题解答 ## 问题1:Context不应该包含数据写入读取功能 **您的思考:** ✅ **完全正确** Context应该专注于状态管理和流程控制,数据读写应该交给Request、Response或Connection完成。 **新的设计:** ```go // Context只负责状态管理 type Context interface { context.Context Request() Request // 获取Request对象 Response() Response // 获取Response对象 Connection() Connection // 获取Connection对象 Set(key string, value interface{}) Get(key string) interface{} } // Request负责数据读取 type Request interface { Raw() []byte // 原始数据 Data() []byte // 协议解码后的数据 Decode(v interface{}) error // 解码为Go对象 Header() FrameHeader // 协议帧头 } // Response负责数据写入 type Response interface { Write(data interface{}) error // 写入数据(自动编码) WriteBytes(data []byte) error // 写入原始字节 SetHeader(header FrameHeader) // 设置协议帧头 Send() error // 发送响应 } ``` ## 问题2:协议帧 = 帧头(协议处理)+ 帧数据(Codec处理) **您的理解:** ✅ **完全正确** 协议帧的结构: ``` [帧头] + [数据] ↓ ↓ Protocol Codec ``` **设计实现:** ```go // Protocol处理帧头 type Protocol interface { HasHeader() bool // 是否有帧头 Encode(data []byte, header FrameHeader) ([]byte, error) // 添加帧头 Decode(data []byte) (FrameHeader, []byte, error) // 提取帧头和数据 } // Codec处理数据序列化 type Codec interface { Encode(v interface{}) ([]byte, error) // 序列化 Decode(data []byte, v interface{}) error // 反序列化 } ``` **数据流程:** 读数据: ``` 原始字节 → Protocol.Decode() → 帧头 + 数据 → Codec.Decode() → Go对象 ``` 写数据: ``` Go对象 → Codec.Encode() → 数据 → Protocol.Encode() → 帧头 + 数据 → 原始字节 ``` ## 问题3:写数据时希望可以连同帧头一起写入 **您的需求:** ✅ **已支持** **实现方式:** ### 方式1:自动处理(推荐) ```go func handler(ctx context.Context) error { resp := ctx.Response() // 设置协议帧头 header := resp.Header() if header != nil { header.Set("message_type", 0x01) header.Set("sequence", 123) } // 写入数据(自动添加帧头) return resp.Write(MyResponse{Code: 200}) } ``` ### 方式2:手动构建 ```go func handler(ctx context.Context) error { resp := ctx.Response() // 手动构建帧头 header := NewFrameHeader() header.Set("message_type", 0x01) resp.SetHeader(header) // 写入数据 return resp.Write(MyResponse{Code: 200}) } ``` ### 方式3:直接写入原始字节 ```go func handler(ctx context.Context) error { resp := ctx.Response() // 手动构建完整的协议帧 frameHeader := []byte{0x01, 0x02, 0x03} // 自定义帧头 data := []byte("your data") frame := append(frameHeader, data...) // 直接写入(绕过自动编码) return resp.WriteBytes(frame) } ``` ## 问题4:无帧头协议支持(如\n分割) **您的需求:** ✅ **已支持** **实现方式:** ### 无帧头协议实现 ```go type NoHeaderProtocol struct{} func (p *NoHeaderProtocol) HasHeader() bool { return false // 无帧头 } func (p *NoHeaderProtocol) Encode(data []byte, header FrameHeader) ([]byte, error) { // 无帧头协议,直接返回数据,添加分隔符 return append(data, '\n'), nil } func (p *NoHeaderProtocol) Decode(data []byte) (FrameHeader, []byte, error) { // 无帧头协议,直接返回数据(去除分隔符) data = bytes.TrimSuffix(data, []byte{'\n'}) return nil, data, nil // 返回nil header } ``` ### 使用示例 ```go func handler(ctx context.Context) error { req := ctx.Request() resp := ctx.Response() // 无帧头协议,直接读取数据 rawData := req.Data() // 已经是去除分隔符的数据 // 处理数据 result := processData(rawData) // 写入响应(协议会自动添加\n) return resp.WriteString(result) } ``` ## 问题5:综合考虑路由、协议选择、协议版本等功能 **您的需求:** ✅ **已考虑** ### 路由集成 路由可以在不同层次进行匹配: 1. **协议层匹配**:根据协议帧头匹配 ```go // 根据帧头的message_type字段匹配 router.RegisterFrameHeader("message_type", "==", 0x01, handler) ``` 2. **数据层匹配**:根据解码后的数据匹配 ```go // 根据JSON数据的path字段匹配 router.RegisterFrameData("path", "==", "/api/user", handler) ``` 3. **原始数据匹配**:根据原始字节匹配(无帧头协议) ```go // 根据原始字符串匹配 router.RegisterString("get_user\n", handler) ``` ### 协议选择 ```go // 配置协议 cfg := &Config{ Protocol: ProtocolConfig{ Name: "nnet", // 协议名称 Version: "1.0", // 协议版本 HasHeader: true, // 是否有帧头 }, } // 服务器自动选择协议 server := NewServer(cfg) ``` ### 协议版本管理 ```go // 协议管理器支持多版本 protocolManager.Register(nnetProtocolV1) // 版本1.0 protocolManager.Register(nnetProtocolV2) // 版本2.0 // 根据数据自动识别版本 protocol, version := protocolManager.Identify(data) ``` ## 问题6:API设计要精简、现代化 **您的需求:** ✅ **已实现** ### API特点 1. **简洁直观** ```go // 读取数据 req.Decode(&data) // 写入数据 resp.Write(data) ``` 2. **类型安全** ```go // 使用接口和泛型保证类型安全 req.Decode(&MyRequest{}) resp.Write(MyResponse{}) ``` 3. **链式调用** ```go // 支持流畅的API resp.Header().Set("type", 0x01).Write(data) ``` 4. **自动处理** ```go // 自动编码/解码 req.Decode(&data) // 自动进行protocol decode + codec decode resp.Write(data) // 自动进行codec encode + protocol encode ``` ## 完整的数据流程 ### 读数据流程 ``` 1. Connection.Read() → []byte (原始字节) ↓ 2. Protocol.Decode() → FrameHeader + []byte (帧头 + 数据) ↓ 3. Request.Data() → []byte (数据部分) ↓ 4. Request.Decode() → interface{} (Go对象,经过codec decode) ↓ 5. 路由匹配(可以根据帧头或数据匹配) ↓ 6. 处理器使用解码后的数据 ``` ### 写数据流程 ``` 1. Response.Write(interface{}) → Go对象 ↓ 2. Codec.Encode() → []byte (序列化后的数据) ↓ 3. Protocol.Encode() → []byte (添加帧头) ↓ 4. Connection.Write() → 发送到客户端 ``` ## 实现状态 ### ✅ 已完成 - [x] 接口定义(Context、Request、Response、Protocol、FrameHeader) - [x] 设计文档 - [x] API设计文档 ### 🚧 进行中 - [ ] Request和Response的具体实现 - [ ] 协议实现的更新 - [ ] 服务器代码的更新 ### 📋 待实现 - [ ] 测试用例 - [ ] 性能优化 - [ ] 文档更新 ## 总结 新的架构设计完全满足您的所有需求: 1. ✅ Context不包含数据读写功能 2. ✅ 协议帧 = 帧头(Protocol)+ 数据(Codec) 3. ✅ 支持连同帧头一起写入 4. ✅ 支持无帧头协议 5. ✅ 综合考虑路由、协议选择、协议版本 6. ✅ API设计精简、现代化 接下来可以开始实现具体的功能。