服务端一元拦截器注册后没反应的最常见原因是注册方式错误或函数签名不匹配:必须用grpc.UnaryInterceptor(yourFunc)显式传入,且签名须严格为func(context.Context, interface{}, *grpc.UnaryServerInfo, grpc.UnaryHandler) (interface{}, error),否则运行时handler为nil导致panic。

Go 语言中 gRPC 没有“服务端插件”概念,所谓拦截必须通过显式注册的 grpc.UnaryInterceptor 或 grpc.StreamInterceptor 实现,漏掉注册就完全不生效。
服务端一元拦截器为什么注册后没反应?
最常见原因是注册方式错误或签名不匹配:
-
grpc.NewServer()必须传入grpc.UnaryInterceptor(yourFunc),写成grpc.UnaryInterceptor{yourFunc}或漏掉括号会静默失败 - 函数签名必须严格为
func(context.Context, interface{}, *grpc.UnaryServerInfo, grpc.UnaryHandler) (interface{}, error),少一个参数、类型错位、返回值顺序颠倒,编译能过但运行时handler为nil,调用时 panic - 如果用了
go-grpc-middleware,必须用grpc_middleware.ChainUnaryServer()组合,直接把多个函数塞进grpc.UnaryInterceptor()会只执行第一个
metadata 中的 token 怎么取才不会空 panic?
从 context 提取 metadata 是高频出错点:
- 必须用
metadata.FromIncomingContext(ctx),不是FromOutgoingContext—— 后者是客户端发请求时用的 - 返回的
ok值必须检查:md, ok := metadata.FromIncomingContext(ctx); if !ok { return nil, status.Error(codes.Internal, "no metadata") } -
md.Get("authorization")返回的是[]string,取值要判空:if len(token) == 0 || token[0] == "",不能直接token[0] == "xxx" - 键名必须小写:
"Authorization"或"AUTHORIZATION"都拿不到值,gRPC 内部统一转为小写存储
流式拦截器为啥日志里看不到请求体?
因为 grpc.StreamServerInterceptor 的参数只有 grpc.ServerStream 接口,原始消息不在参数里:
- 不能像一元那样直接读
req,必须包装ServerStream,重写RecvMsg和SendMsg方法才能捕获数据 - 想记录首条请求,要在包装后的
RecvMsg里做;想记录最后响应,得在SendMsg里判断是否为终态 - 多个流式拦截器叠加时,
go-grpc-middleware的ChainStreamServer是必需的,手写链容易漏掉return handler(srv, wrappedStream)导致流卡死
客户端拦截器怎么安全加 auth header?
唯一可靠方式是用 metadata.AppendToOutgoingContext:
- 不要手动构造
metadata.MD然后塞进context.WithValue,gRPC 完全忽略这种写法 - 正确写法:
ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer "+token) - 如果 token 来自外部(如 JWT),务必在拦截器开头校验非空和格式,否则空字符串会导致 server 端
md.Get("authorization")返回空切片,鉴权逻辑误判 - 多个客户端拦截器(如 auth + retry + timeout)顺序很重要:
grpc.WithUnaryInterceptor(auth, retry, log)表示 auth 最外层,log 最内层,超时控制应由上层 context 设置,拦截器里别碰ctx的 deadline
真正难的不是写一个拦截器,而是让多个拦截器在生命周期、错误传播、上下文传递上不互相干扰——尤其是流式场景下,RecvMsg 和 SendMsg 的调用时机、error 是否透出、defer 日志位置,稍不注意就会丢消息或掩盖真实错误。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











