# 服务端如何写数据到客户端 ## 概述 nnet库提供了多种方式将数据从服务端写入到客户端,支持任意类型的数据,并自动匹配编解码器进行编码。 ## 方式一:写入字节数据(基础方式) ```go func handler(ctx context.Context) error { // 直接写入字节数据 data := []byte("Hello, World!") return ctx.Write(data) } ``` ## 方式二:写入字符串 ```go func handler(ctx context.Context) error { // 写入字符串 return ctx.WriteString("Hello, World!") } ``` ## 方式三:写入任意类型(自动编码)⭐ 这是最推荐的方式,支持任意类型的数据,会自动使用配置的编解码器进行编码。 ### 基本使用 ```go type Response struct { Code int `json:"code"` Message string `json:"message"` Data interface{} `json:"data"` } func handler(ctx context.Context) error { // 写入结构体(自动使用JSON编码) resp := Response{ Code: 200, Message: "success", Data: map[string]interface{}{"user_id": 123}, } return ctx.WriteAny(resp) } ``` ### 指定编解码器 ```go func handler(ctx context.Context) error { resp := Response{ Code: 200, Message: "success", } // 使用JSON编解码器 ctx.WriteAnyWithCodec(resp, "json") // 使用MessagePack编解码器 ctx.WriteAnyWithCodec(resp, "msgpack") // 使用Protobuf编解码器(需要实现proto.Message接口) ctx.WriteAnyWithCodec(resp, "protobuf") return nil } ``` ## 方式四:协议层编码(可选) 如果启用了协议层编码,数据会先使用编解码器编码,然后再使用协议编码(如nnet协议的Magic、长度、校验和等)。 ### 配置协议层编码 ```go cfg := &nnet.Config{ Addr: "tcp://:8080", Codec: &nnet.CodecConfig{ DefaultCodec: "json", EnableProtocolEncode: true, // 启用协议层编码 }, } server, err := nnet.NewServer(cfg) ``` ### 使用示例 ```go func handler(ctx context.Context) error { // 数据会先使用JSON编码,然后使用协议编码(如nnet协议) resp := Response{Code: 200, Message: "success"} return ctx.WriteAny(resp) } ``` ## 完整示例 ```go package main import ( "github.com/noahlann/nnet" ctxpkg "github.com/noahlann/nnet/pkg/context" ) type User struct { ID int `json:"id"` Name string `json:"name"` } type Response struct { Code int `json:"code"` Data interface{} `json:"data"` } func main() { // 创建服务器配置 cfg := &nnet.Config{ Addr: "tcp://:8080", Codec: &nnet.CodecConfig{ DefaultCodec: "json", // 显式使用JSON编解码器 EnableProtocolEncode: false, // 不启用协议层编码 }, } // 创建服务器 server, err := nnet.NewServer(cfg) if err != nil { panic(err) } // 注册路由处理器 server.Router().RegisterString("get_user", getUserHandler) server.Router().RegisterString("list_users", listUsersHandler) // 启动服务器 server.Start() } // 处理器1:返回单个用户(使用默认编解码器,binary) func getUserHandler(ctx ctxpkg.Context) error { user := User{ ID: 1, Name: "Alice", } resp := Response{ Code: 200, Data: user, } // 自动使用JSON编码 return ctx.WriteAny(resp) } // 处理器2:返回用户列表 func listUsersHandler(ctx ctxpkg.Context) error { users := []User{ {ID: 1, Name: "Alice"}, {ID: 2, Name: "Bob"}, } resp := Response{ Code: 200, Data: users, } return ctx.WriteAny(resp) } // 处理器3:使用指定的编解码器 func getUserWithMsgpack(ctx ctxpkg.Context) error { user := User{ID: 1, Name: "Alice"} resp := Response{Code: 200, Data: user} // 使用MessagePack编码 return ctx.WriteAnyWithCodec(resp, "msgpack") } ``` ## 支持的编解码器 1. **JSON**(可选,默认是 binary) - 支持所有可序列化的Go类型 - 使用标准库的`encoding/json` 2. **Binary** - 支持基本数值类型和字节数组 - 使用二进制编码 3. **Protobuf** - 需要实现`proto.Message`接口 - 使用Google Protocol Buffers 4. **MessagePack** - 支持所有可序列化的Go类型 - 比JSON更紧凑的二进制格式 ## 编解码器注册 服务器会自动注册以下编解码器: - `json` - JSON编解码器(可选;默认为 binary) - `binary` - 二进制编解码器 - `protobuf` - Protobuf编解码器 - `