grpc是当前最稳妥的微服务通信选择,必须配对使用proto3、正确tls配置与连接复用;proto3字段需严格对齐go结构体,嵌入unimplementedxxxserver,复用clientconn并显式关闭,流式调用须持续检查上下文错误。

直接用 net/rpc 不行,它不支持 TLS、超时、跨语言,也不适合微服务生产环境;gRPC 是当前最稳妥的选择,但必须配对使用 proto3 + 正确的 TLS 配置 + 连接复用,否则容易出现静默失败或连接拒绝。
proto3 定义与 Go 结构体字段必须严格对齐
gRPC 的序列化和反序列化依赖 Protocol Buffers 的契约一致性,任何字段名、类型、标签不匹配都会导致数据丢失或解析 panic。
-
syntax = "proto3"是硬性要求,proto2 的默认值语义会干扰 Go 端空值判断 - 所有 message 字段用
snake_case,并显式加[json_name = "user_id"],否则生成的 Go struct json 标签会错位 -
repeated string tags = 1;对应 Go 切片,但nil切片不会被序列化,建议初始化为[]string{} - 服务方法必须写全
rpc GetUser(UserRequest) returns (UserResponse);,漏掉returns会导致生成代码缺失返回类型
客户端连接不能每次调用都 grpc.Dial
频繁新建 *grpc.ClientConn 会触发大量 TCP 握手和 TLS 协商,吞吐量断崖下跌,且容易耗尽文件描述符。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 全局复用单个
*grpc.ClientConn,它是线程安全的,可并发调用多个 service 方法 - 开发调试时可用
grpc.WithBlock()让Dial阻塞直到连接就绪;线上必须去掉,改用context.WithTimeout控制建连时间 - 务必传入凭证:本地用
grpc.WithTransportCredentials(insecure.NewCredentials()),生产用grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)) - 连接关闭必须显式调用
conn.Close(),尤其在服务退出阶段,否则 goroutine 和连接泄漏
服务端必须嵌入 UnimplementedXXXServer
这是最容易被忽略却最致命的坑:没嵌入空实现,调用未实现的方法会直接 panic,而不是返回 status.CodeUnimplemented。
- 你的 server struct 必须嵌入自动生成的
UnimplementedUserServiceServer,例如:type userServer struct{ pb.UnimplementedUserServiceServer } - 即使只实现部分方法,也绝不能省略嵌入;否则任意未注册方法被调用,gRPC 就 panic
- 注册时不能传
nil:比如pb.RegisterUserServiceServer(srv, nil)会立刻 panic,哪怕还没发起一次调用 - 流式响应中,必须持续检查
stream.Context().Err() != nil,并在每次stream.Send()后判断错误,否则缓冲区堆积会卡死连接
真正难的不是写通第一个 RPC 调用,而是让每个环节都“不意外”——字段对不上、连接没复用、空实现没嵌入、流式没判错,任何一个点漏掉,都会在压测或上线后突然失效,而且错误日志极少。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










