|
|
# 服务端写数据到客户端 - 问题解答
|
|
|
|
|
|
## 问题
|
|
|
|
|
|
1. 服务端如何写数据到客户端?
|
|
|
2. 是否支持any类型?
|
|
|
3. 通过协议自动匹配编码器?
|
|
|
|
|
|
## 答案
|
|
|
|
|
|
### 1. 服务端如何写数据到客户端?
|
|
|
|
|
|
nnet库提供了多种方式将数据从服务端写入到客户端:
|
|
|
|
|
|
#### 方式一:直接写入字节数据
|
|
|
```go
|
|
|
func handler(ctx ctxpkg.Context) error {
|
|
|
data := []byte("Hello, World!")
|
|
|
return ctx.Write(data)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
#### 方式二:写入字符串
|
|
|
```go
|
|
|
func handler(ctx ctxpkg.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 ctxpkg.Context) error {
|
|
|
resp := Response{
|
|
|
Code: 200,
|
|
|
Message: "success",
|
|
|
Data: map[string]interface{}{"user_id": 123},
|
|
|
}
|
|
|
// 自动使用配置的默认编解码器(库默认是 binary)
|
|
|
return ctx.WriteAny(resp)
|
|
|
}
|
|
|
```
|
|
|
|
|
|
### 2. 是否支持any类型?
|
|
|
|
|
|
**是的,完全支持!**
|
|
|
|
|
|
nnet库支持写入任意Go类型:
|
|
|
- ✅ 结构体(struct)
|
|
|
- ✅ 映射(map)
|
|
|
- ✅ 切片(slice)
|
|
|
- ✅ 数组(array)
|
|
|
- ✅ 基本类型(int, string, bool等)
|
|
|
- ✅ 接口类型(interface{})
|
|
|
|
|
|
使用`ctx.WriteAny(data)`方法,nnet会自动:
|
|
|
1. 检测数据类型
|
|
|
2. 选择合适的编解码器
|
|
|
3. 编码数据
|
|
|
4. 写入客户端
|
|
|
|
|
|
### 3. 通过协议自动匹配编码器?
|
|
|
|
|
|
**是的,完全支持!**
|
|
|
|
|
|
nnet库提供了**自动编解码器匹配**功能:
|
|
|
|
|
|
#### 自动匹配机制
|
|
|
|
|
|
1. **默认编解码器**:根据配置自动选择默认编解码器(库默认 binary)
|
|
|
```go
|
|
|
cfg := &nnet.Config{
|
|
|
Codec: &nnet.CodecConfig{
|
|
|
DefaultCodec: "json", // 显式使用JSON
|
|
|
},
|
|
|
}
|
|
|
```
|
|
|
|
|
|
2. **自动编码**:使用`WriteAny`时,自动使用默认编解码器(默认 binary)
|
|
|
```go
|
|
|
ctx.WriteAny(data) // 自动使用JSON编码
|
|
|
```
|
|
|
|
|
|
3. **指定编解码器**:可以指定使用哪个编解码器
|
|
|
```go
|
|
|
ctx.WriteAnyWithCodec(data, "json") // 使用JSON
|
|
|
ctx.WriteAnyWithCodec(data, "msgpack") // 使用MessagePack
|
|
|
ctx.WriteAnyWithCodec(data, "protobuf") // 使用Protobuf
|
|
|
```
|
|
|
|
|
|
#### 协议层编码(可选)
|
|
|
|
|
|
nnet还支持**协议层编码**,可以在编解码器编码的基础上,再进行协议层编码:
|
|
|
|
|
|
```go
|
|
|
cfg := &nnet.Config{
|
|
|
Codec: &nnet.CodecConfig{
|
|
|
DefaultCodec: "json",
|
|
|
EnableProtocolEncode: true, // 启用协议层编码
|
|
|
},
|
|
|
}
|
|
|
```
|
|
|
|
|
|
启用后,数据会经过:
|
|
|
1. **编解码器编码**:Go对象 → JSON字节数组
|
|
|
2. **协议编码**:JSON字节数组 → nnet协议格式(包含Magic、长度、校验和等)
|
|
|
|
|
|
## 完整示例
|
|
|
|
|
|
```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", func(ctx ctxpkg.Context) error {
|
|
|
user := User{ID: 1, Name: "Alice"}
|
|
|
resp := Response{Code: 200, Data: user}
|
|
|
|
|
|
// 方式1:自动使用JSON编码(推荐)
|
|
|
return ctx.WriteAny(resp)
|
|
|
|
|
|
// 方式2:指定使用MessagePack编码
|
|
|
// return ctx.WriteAnyWithCodec(resp, "msgpack")
|
|
|
|
|
|
// 方式3:直接写入字符串
|
|
|
// return ctx.WriteString("Hello, World!")
|
|
|
})
|
|
|
|
|
|
// 启动服务器
|
|
|
server.Start()
|
|
|
}
|
|
|
```
|
|
|
|
|
|
## 支持的编解码器
|
|
|
|
|
|
nnet库自动注册以下编解码器:
|
|
|
- **JSON**(可选,默认 binary):支持所有可序列化的Go类型
|
|
|
- **Binary**:支持基本数值类型和字节数组
|
|
|
- **Protobuf**:需要实现`proto.Message`接口
|
|
|
- **MessagePack**:支持所有可序列化的Go类型
|
|
|
|
|
|
## 自定义编解码器
|
|
|
|
|
|
```go
|
|
|
// 注册自定义编解码器
|
|
|
server.CodecRegistry().Register("mycodec", myCodec)
|
|
|
|
|
|
// 使用自定义编解码器
|
|
|
ctx.WriteAnyWithCodec(data, "mycodec")
|
|
|
```
|
|
|
|
|
|
## 总结
|
|
|
|
|
|
✅ **服务端写数据**:支持`Write`、`WriteString`、`WriteAny`三种方式
|
|
|
✅ **支持any类型**:完全支持任意Go类型
|
|
|
✅ **自动匹配编码器**:根据配置自动选择编解码器,也可以手动指定
|
|
|
✅ **协议层编码**:可选地支持协议层编码(如nnet协议)
|
|
|
|
|
|
所有功能已实现并测试通过!
|
|
|
|