When building REST APIs or web applications in Go, one of the essential tasks is validating incoming request data. Having worked on various small to medium-sized projects in Golang—most of which are microservices providing RESTful APIs—I’ve employed several approaches to handle data validation.
Among these, there’s one method I frequently rely on. For validating application/json or text/plain requests, I begin by defining a struct type to represent the specific request payload. Then, I implement a Validate method on that struct to encapsulate the validation logic.
This approach is my first choice when handling JSON payloads. However, for other types of input—such as form-data, query strings, or x-www-form-urlencoded requests—the process differs slightly.
For more complex validation scenarios, I often use the govalidator library. While it provides extensive features, I’ve found that it can sometimes take more effort to validate requests than to implement the business logic itself. Additionally, whenever validation rules change, updating the corresponding error messages can become tedious.
To address these challenges, I developed a simple validation package for handling request validation in Golang more efficiently. Here’s a look at how it works:
This approach is cleaner and simpler, making it easy to modify validation rules as needed. If you require a custom validation rule—such as checking for a unique username—you can effortlessly integrate it into the system. Adding custom rules is straightforward, allowing you to tailor validations to your specific requirements.
Here’s an example of how to add a custom rule:
Adding custom rules is straightforward, but I’m still exploring the best practices for request validation. Using struct tags or strings to define validation rules often feels limiting and inflexible, especially for more complex scenarios. I hope the Go community will come up with more robust and elegant solutions for validating incoming requests in the future.
I’d love to hear your thoughts on this topic. What approaches do you prefer for request validation in Go or other languages? How do you strike a balance between simplicity and flexibility in your validation logic?