Go标准库net/rpc默认不支持Header,需自定义扩展:方案一修改消息结构封装Header;方案二利用HTTP层复用Header;方案三升级gRPC原生支持Metadata;均需注意键名冲突、长度限制与敏感信息防护。
Go 语言标准库的 net/rpc 默认不支持自定义 Header 或 Metadata,它只基于简单的编码(如 Gob、JSON)传输请求和响应体。若需在 RPC 调用中传递认证 Token、TraceID、租户 ID 等上下文信息,必须自行扩展协议层。核心思路是:**在序列化前注入元数据,在反序列化后提取元数据,并确保客户端和服务端对格式达成一致。**
不依赖 gRPC,纯用 net/rpc,可通过包装 rpc.Call 和 rpc.ServerCodec 实现。关键是在每个请求/响应体外再套一层带 Header 的结构:
type RPCMessage struct {
Header map[string]string `json:"header"`
Body interface{} `json:"body"`
}
ClientCodec:在 WriteRequest 中将原 RequestBody 封装进 RPCMessage.Body,同时把 context.Value 中的 metadata 写入 Header;ReadResponseHeader 则先解出 RPCMessage,再从 Header 提取元数据存入本地 context(如通过 context.WithValue)。ServerCodec 在 ReadRequestHeader 解出 Header 并注入 handler 的 context;WriteResponse 可选择性返回 Header(如透传 TraceID)。如果 RPC 基于 HTTP(比如用 http.ServeMux 暴露 JSON-RPC 接口),可直接复用 HTTP Header:
http.Client 发起 POST 请求,手动设置 X-Auth-Token、X-Trace-ID 等 Header;http.Handler 中解析 Header,注入到 RPC 调用的 context 中(例如通过 rpc.DefaultServer.RegisterName 注册的 handler 包裹一层中间件);jsonrpc2 或 net/rpc/jsonr
pc 不解析 HTTP Header,需自己桥接——即不走 rpc.ServeHTTP,而是手写 handler 解析 HTTP body + header,再调用 server.ServeCodec。若项目允许技术栈升级,gRPC 原生支持 Metadata(即 Header):
ctx = metadata.AppendToOutgoingContext(ctx, "auth", "Bearer xxx", "tenant", "acme");md, ok := metadata.FromIncomingContext(ctx),即可读取所有键值对;无论哪种方式,都要注意:
Content-Type、Connection 等 HTTP 保留字段);json.Encoder),且 io.ReadCloser / io.WriteCloser 生命周期管理正确,否则会卡死或 panic。基本上就这些。自定义 Header 的本质是“在协议边界上多塞一层上下文”,不复杂但容易忽略序列化一致性与生命周期控制。