Top Related Projects
Go support for Google's protocol buffers
Go support for Google's protocol buffers
Protocol Buffer Validation - Being replaced by github.com/bufbuild/protovalidate
Quick Overview
The mwitkow/go-proto-validators
project is a Go library that provides a set of validation rules for Protocol Buffers (protobuf) messages. It allows developers to define validation constraints directly in the protobuf schema, which can then be automatically enforced at runtime.
Pros
- Declarative Validation: The library allows developers to define validation rules directly in the protobuf schema, making it easier to manage and maintain validation logic.
- Automatic Validation: The generated code from the protobuf compiler automatically includes the validation logic, reducing the amount of boilerplate code that developers need to write.
- Extensibility: The library provides a set of built-in validation rules, but also allows developers to define custom validation rules as needed.
- Integration with Existing Tooling: The library integrates well with the existing protobuf toolchain, making it easy to incorporate into existing projects.
Cons
- Dependency on Protobuf: The library is tightly coupled with the protobuf ecosystem, which may not be suitable for projects that do not use protobuf.
- Limited Validation Types: While the library provides a set of built-in validation rules, it may not cover all the validation requirements that developers might have.
- Performance Impact: Depending on the complexity of the validation rules, the library may have a performance impact on the application.
- Lack of Comprehensive Documentation: The project's documentation could be more comprehensive, making it harder for new users to get started.
Code Examples
Here are a few examples of how to use the mwitkow/go-proto-validators
library:
- Defining Validation Rules in the Protobuf Schema:
message Person {
string name = 1 [(validator.field) = {string_not_empty: true}];
int32 age = 2 [(validator.field) = {int_gt: 0, int_lt: 150}];
repeated string emails = 3 [(validator.field) = {repeated_min_items: 1, repeated_max_items: 5}];
}
- Validating a Protobuf Message:
import (
"github.com/mwitkow/go-proto-validators"
)
func ValidatePerson(p *Person) error {
if _, err := validators.ValidateStruct(p); err != nil {
return err
}
return nil
}
- Defining a Custom Validation Rule:
import (
"github.com/mwitkow/go-proto-validators"
)
func init() {
validators.RegisterValidatorFunc("is_even", func(v interface{}) error {
if i, ok := v.(int32); ok {
if i%2 != 0 {
return fmt.Errorf("%d is not an even number", i)
}
}
return nil
})
}
message Person {
int32 age = 2 [(validator.field) = {is_even: true}];
}
Getting Started
To get started with the mwitkow/go-proto-validators
library, follow these steps:
- Install the library using Go modules:
go get github.com/mwitkow/go-proto-validators
- Define your protobuf messages with validation rules:
syntax = "proto3";
package example;
import "github.com/mwitkow/go-proto-validators/validator.proto";
message Person {
string name = 1 [(validator.field) = {string_not_empty: true}];
int32 age = 2 [(validator.field) = {int_gt: 0, int_lt: 150}];
repeated string emails = 3 [(validator.field) = {repeated_min_items: 1, repeated_max_items: 5}];
}
- Generate the Go code for your protobuf messages:
protoc --go_out=. --go-validator_out=. example.proto
- Use the generated validation functions in your Go code:
import
Competitor Comparisons
Go support for Google's protocol buffers
Pros of protobuf-go
- Official implementation by Google, ensuring compatibility and long-term support
- Comprehensive support for all Protocol Buffers features
- Optimized performance for encoding and decoding
Cons of protobuf-go
- Lacks built-in validation functionality
- Requires additional code or libraries for custom validation rules
Code Comparison
go-proto-validators:
message User {
string email = 1 [(validator.field) = {regex: "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$"}];
int32 age = 2 [(validator.field) = {int_gt: 0, int_lt: 120}];
}
protobuf-go (with custom validation):
type User struct {
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
Age int32 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"`
}
func (u *User) Validate() error {
if !regexp.MustCompile(`^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$`).MatchString(u.Email) {
return errors.New("invalid email format")
}
if u.Age <= 0 || u.Age >= 120 {
return errors.New("age must be between 1 and 119")
}
return nil
}
go-proto-validators provides a more concise and declarative way to define validation rules directly in the protocol buffer definition. protobuf-go requires manual implementation of validation logic in Go code, which can be more verbose but offers greater flexibility for complex validation scenarios.
Go support for Google's protocol buffers
Pros of protobuf
- Official Google implementation, ensuring compatibility and long-term support
- Comprehensive feature set covering all aspects of Protocol Buffers
- Extensive documentation and community support
Cons of protobuf
- Lacks built-in validation features for generated Go code
- More complex to use for simple validation tasks
- Requires additional code or libraries for custom validations
Code Comparison
go-proto-validators:
message User {
string name = 1 [(validator.field) = {regex: "^[a-z]{2,5}$"}];
int32 age = 2 [(validator.field) = {int_gt: 0, int_lt: 100}];
}
protobuf:
message User {
string name = 1;
int32 age = 2;
}
// Additional validation code required
Key Differences
- go-proto-validators focuses on adding validation rules directly in .proto files
- protobuf provides a more general-purpose implementation without built-in validations
- go-proto-validators simplifies the validation process for Go developers
- protobuf requires manual implementation of validation logic in Go code
Use Cases
- Choose go-proto-validators for projects requiring extensive field validations
- Opt for protobuf in larger projects needing full Protocol Buffers functionality
- Consider go-proto-validators for rapid development with built-in validations
- Use protobuf when working with multiple languages or requiring official support
Protocol Buffer Validation - Being replaced by github.com/bufbuild/protovalidate
Pros of protoc-gen-validate
- Multi-language support: Generates validators for Go, C++, Java, and Python
- More extensive validation options, including complex rules and cross-field validations
- Active development and maintenance with regular updates
Cons of protoc-gen-validate
- Steeper learning curve due to more complex syntax and options
- Potentially larger generated code size for simple validations
Code Comparison
go-proto-validators:
message Example {
string email = 1 [(validator.field) = {regex: "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$"}];
}
protoc-gen-validate:
message Example {
string email = 1 [(validate.rules).string = {
email: true,
max_len: 100
}];
}
Both libraries provide validation for Protocol Buffer messages, but protoc-gen-validate offers more comprehensive features and multi-language support. go-proto-validators is simpler and more lightweight, focusing solely on Go. The code comparison shows that protoc-gen-validate has a more structured approach to defining validation rules, while go-proto-validators uses a more compact syntax. Choose based on your project's complexity, language requirements, and desired level of validation granularity.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Golang ProtoBuf Validator Compiler
A protoc
plugin that generates Validate() error
functions on Go proto struct
s based on field options inside .proto
files. The validation functions are code-generated and thus don't suffer on performance from tag-based reflection on
deeply-nested messages.
Requirements
Using Protobuf validators is currently verified to work with:
- Go 1.11, 1.12, 1.13
- Protobuf @
v3.8.0
- Go Protobuf @
v1.3.2
- Gogo Protobuf @
v1.3.0
It should still be possible to use it in project using earlier Go versions. However if you want to contribute to this repository you'll need at least 1.11 for Go module support.
Paint me a code picture
Let's take the following proto3
snippet:
syntax = "proto3";
package validator.examples;
import "github.com/mwitkow/go-proto-validators/validator.proto";
message InnerMessage {
// some_integer can only be in range (0, 100).
int32 some_integer = 1 [(validator.field) = {int_gt: 0, int_lt: 100}];
// some_float can only be in range (0;1).
double some_float = 2 [(validator.field) = {float_gte: 0, float_lte: 1}];
}
message OuterMessage {
// important_string must be a lowercase alpha-numeric of 5 to 30 characters (RE2 syntax).
string important_string = 1 [(validator.field) = {regex: "^[a-z0-9]{5,30}$"}];
// proto3 doesn't have `required`, the `msg_exist` enforces presence of InnerMessage.
InnerMessage inner = 2 [(validator.field) = {msg_exists : true}];
}
First, the required
keyword is back for proto3
, under the guise of msg_exists
. The painful if-nil
checks are taken care of!
Second, the expected values in fields are now part of the contract .proto
file. No more hunting down conditions in code!
Third, the generated code is understandable and has clear understandable error messages. Take a look:
func (this *InnerMessage) Validate() error {
if !(this.SomeInteger > 0) {
return fmt.Errorf("validation error: InnerMessage.SomeInteger must be greater than '0'")
}
if !(this.SomeInteger < 100) {
return fmt.Errorf("validation error: InnerMessage.SomeInteger must be less than '100'")
}
if !(this.SomeFloat >= 0) {
return fmt.Errorf("validation error: InnerMessage.SomeFloat must be greater than or equal to '0'")
}
if !(this.SomeFloat <= 1) {
return fmt.Errorf("validation error: InnerMessage.SomeFloat must be less than or equal to '1'")
}
return nil
}
var _regex_OuterMessage_ImportantString = regexp.MustCompile("^[a-z0-9]{5,30}$")
func (this *OuterMessage) Validate() error {
if !_regex_OuterMessage_ImportantString.MatchString(this.ImportantString) {
return fmt.Errorf("validation error: OuterMessage.ImportantString must conform to regex '^[a-z0-9]{5,30}$'")
}
if nil == this.Inner {
return fmt.Errorf("validation error: OuterMessage.Inner message must exist")
}
if this.Inner != nil {
if err := validators.CallValidatorIfExists(this.Inner); err != nil {
return err
}
}
return nil
}
Installing and using
The protoc
compiler expects to find plugins named proto-gen-XYZ
on the execution $PATH
. So first:
export PATH=${PATH}:${GOPATH}/bin
Then, do the usual
go get github.com/mwitkow/go-proto-validators/protoc-gen-govalidators
Your protoc
builds probably look very simple like:
protoc \
--proto_path=. \
--go_out=. \
*.proto
That's fine, until you encounter .proto
includes. Because go-proto-validators
uses field options inside the .proto
files themselves, it's .proto
definition (and the Google descriptor.proto
itself) need to on the protoc
include
path. Hence the above becomes:
protoc \
--proto_path=${GOPATH}/src \
--proto_path=${GOPATH}/src/github.com/google/protobuf/src \
--proto_path=. \
--go_out=. \
--govalidators_out=. \
*.proto
Or with gogo protobufs:
protoc \
--proto_path=${GOPATH}/src \
--proto_path=${GOPATH}/src/github.com/gogo/protobuf/protobuf \
--proto_path=. \
--gogo_out=. \
--govalidators_out=gogoimport=true:. \
*.proto
Basically the magical incantation (apart from includes) is the --govalidators_out
. That triggers the
protoc-gen-govalidators
plugin to generate mymessage.validator.pb.go
. That's it :)
License
go-proto-validators
is released under the Apache 2.0 license. See the LICENSE file for details.
Top Related Projects
Go support for Google's protocol buffers
Go support for Google's protocol buffers
Protocol Buffer Validation - Being replaced by github.com/bufbuild/protovalidate
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot