如何将gRPC Protobuf消息字段设置为严格非空?
严格Protobuf定义解决请求字段不校验问题
问题背景
发送POST请求时误用了键UserId而非user_id,但服务器未返回任何错误提示,因此需要创建严格的Protobuf定义,强制校验必填字段,避免此类无提示错误。
现有Protobuf定义
message GarageAndUserId { string user_id = 1; Garage garage = 2; }
生成的Go结构体
type GarageAndUserId struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` Garage *Garage `protobuf:"bytes,2,opt,name=garage,proto3" json:"garage,omitempty"` }
临时手动校验方案
在请求处理函数中添加字段非空判断(注意修正原代码的类型错误):
var requestBody model.GarageAndUserId err := decoder.Decode(&requestBody) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // 注意:string是值类型,不能与nil比较,需判断是否为空字符串 if requestBody.UserId == "" { http.Error(w, "user_id为必填字段", http.StatusBadRequest) return } // 后续业务逻辑
推荐方案:Protobuf内置校验规则定义
Protobuf 3默认字段为可选,但可通过校验扩展实现必填约束。只需在Protobuf定义中添加校验规则,即可自动生成校验逻辑,无需手动编写判断。
完整Protobuf定义
import "google/protobuf/descriptor.proto"; import "validate/validate.proto"; message GarageAndUserId { // 强制字符串非空 string user_id = 1 [(validate.rules).string.min_len = 1]; // 强制消息实例非空 Garage garage = 2 [(validate.rules).message.required = true]; }
配套Go处理逻辑
生成Go代码后,直接调用自动生成的Validate()方法完成校验:
var requestBody model.GarageAndUserId err := decoder.Decode(&requestBody) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // 自动校验所有字段规则 if err := requestBody.Validate(); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } // 后续业务逻辑
这种方式会在字段缺失、为空或不符合规则时,返回明确的错误提示,彻底解决无提示的字段错误问题。
内容的提问来源于stack exchange,提问作者Jason Rich Darmawan
相关产品推荐
相关产品推荐

