A Guide to Input Validation in Go with Validator V10
Tags: go, backend, webdev, coding
Published: 2023-07-25 12:56:05


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmxpwoz327h1152bhxee.png)


## Introduction
Input validation is crucial for data integrity and security in any software application. Go, a powerful and popular programming language known for its simplicity and performance, offers the "validator" package (v10) for efficient validation. In this blog, we explore how to leverage Go [Validator V10](https://github.com/go-playground/validator) to validate input parameters effectively and enhance application robustness.

### 👩‍💻 Validating Input Parameters:
Let's now dive into the practical implementation of input parameter validation using Go Validator V10. For this example, we'll validate input parameters for a simple API endpoint that receives data in JSON format.

#### Step 1: Import the Go Validator package:
To begin, we import the `validator` package in our Go code:

```go
import (
	"fmt"
	"net/http"

	"github.com/go-playground/validator/v10"
)
```
#### Step 2: Define a Data Structure:
Next, we define a Go struct representing the data structure of the input we expect to receive:
```go
type User struct {
	Username  string `json:"username" validate:"required,min=5,max=20"`
	Email     string `json:"email" validate:"required,email"`
	Age       int    `json:"age" validate:"gte=18,lte=120"`
}
```
In this example, we have a User struct with three fields `Username`, `Email`, and `Age`. We've added validation tags using Go Validator V10 syntax to specify the validation rules for each field.
> To access the full list of supported validation tags and their usage, you can refer to the official documentation of Go Validator V10 at the following URL: https://pkg.go.dev/github.com/go-playground/validator/v10

#### Step 3: Validate the Input:
Now, let's implement the API endpoint and validate the incoming data:
```go
func createUserHandler(w http.ResponseWriter, r *http.Request) {
	var user User

	// Parse the JSON request and populate the User struct
	err := json.NewDecoder(r.Body).Decode(&user)
	if err != nil {
		http.Error(w, "Invalid JSON", http.StatusBadRequest)
		return
	}

	// Create a new validator instance
	validate := validator.New()

	// Validate the User struct
	err = validate.Struct(user)
	if err != nil {
		// Validation failed, handle the error
		errors := err.(validator.ValidationErrors)
		http.Error(w, fmt.Sprintf("Validation error: %s", errors), http.StatusBadRequest)
		return
	}

	// Validation passed, proceed to process the user data
	// Your application logic goes here...

	// Send a success response
	w.WriteHeader(http.StatusOK)
	fmt.Fprintf(w, "User created successfully!")
}
```
In this code snippet, we first parse the incoming JSON data and populate the User struct. Then, we create a new validator instance and validate the User struct using `validate.Struct(user)`. If validation fails, the error message with the specific validation errors will be returned. Otherwise, our application logic can continue to process the validated data.

### 🚀 Creating Custom Validators 🚀
Apart from the built-in validation tags provided by Go Validator V10, you also have the flexibility to create custom validators tailored to your specific application requirements. Custom validators allow you to enforce domain-specific rules on your data, ensuring even more precise input validation.

Here's an example of creating a custom validator named **PercentageValidator**
```go
import (
	"github.com/go-playground/validator/v10"
	"github.com/shopspring/decimal"
)

func PercentageValidator(fl validator.FieldLevel) bool {
	maxPercent := decimal.NewFromInt(100)
	minPercent := decimal.NewFromInt(0)

	switch v := fl.Field(); v.Kind() {
	case reflect.String:
		val, err := decimal.NewFromString(v.String())
		if err == nil && val.Abs().GreaterThanOrEqual(minPercent) && val.Abs().LessThanOrEqual(maxPercent) {
			return true
		}
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		val := decimal.NewFromInt(v.Int())
		if val.Abs().GreaterThanOrEqual(minPercent) && val.Abs().LessThanOrEqual(maxPercent) {
			return true
		}
	case reflect.Float32, reflect.Float64:
		val := decimal.NewFromFloat(v.Float())
		if val.Abs().GreaterThanOrEqual(minPercent) && val.Abs().LessThanOrEqual(maxPercent) {
			return true
		}
	default:
		return false
	}

	return false
}
```
In this example, the `PercentageValidator` function checks whether the input value represents a valid percentage (ranging from 0 to 100). The validator supports various data types, including `strings`, `integers`, and `floats`.

To use this custom validator, you need to register it with Go Validator V10 before performing input validation. You can register it in the following way:

```go
validate := validator.New()

// Registering the custom validator
validate.RegisterValidation("percentage", PercentageValidator)
```

Now you can apply the `percentage` validation tag to any field that requires percentage validation in your User struct or any other data structure:

```go
type User struct {
	Username  string `json:"username" validate:"required,min=5,max=20"`
	Email     string `json:"email" validate:"required,email"`
	Age       int    `json:"age" validate:"gte=18,lte=120"`
	Discount  float64 `json:"discount" validate:"percentage"`
}
```
By creating custom validators, you can tailor the input validation to your specific application's needs, ensuring the accuracy and security of your data processing.

## 📝 Conclusion:
By using Go [Validator V10](https://github.com/go-playground/validator), we can easily implement input parameter validation in our Go applications. Validating input parameters helps to prevent potential security vulnerabilities and ensures that the data our applications work with is accurate and consistent. The library's rich set of validation rules makes it a powerful tool for developers working with Go.

Remember to always validate the input data in your applications to guarantee their reliability and security. Happy coding!🥂