Input validation in GoLang

Pre-kickoff

if err != nil {
return err
}
syntax annoys me... 🤦‍♂️

Prologue

A Junior Gopher approach

bottleneck:

  • does not scale well
  • extremely non-reusable
  • not flexible
  • time-consuming to maintain when codebase gets bigger and bigger
  • unit testing (don’t be one of those bros who is too good to unit test 💩)

The idiomatic way to Go!

Go Playground Validator

How to use

Key: 'User.Email' Error:Field validation for 'Email' failed on the 'email' tag
Key: 'User.Name' Error:Field validation for 'Name' failed on the 'required' tag

Add custom validation rule

Key: ‘User.Password’ Error:Field validation for ‘Password’ failed on the ‘passwd’ tag`

Customise error messages

Email must be a valid email
Name is a required field
Password is not strong enough
{
"email": "some"
"name": "My",
"password": "123"
}
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
email must be a valid email
name is a required field
password is not strong enough

Yet another approach 🎉

Do not make a mess 💩

Use validator as a dependency

Keep it in the internal package

--project
---cmd
----server
------main.go <- create an instance here, pass all the way down
----lambda
-----my_func
-------main.go <-- do all validations here
----internal
------user
--------handler.go <-- Do all validation here and keep service clean
--------service.go <-- Service will just do the business logic
--------repository.go
------validator
--------validate.go <-- Register all custom rules, messages, trans here

Do not define validation rules on domain entities 🙅‍♂️

I strongly recommend to have a read article
  • a create-user request comes in
  • gets mapped into createUserRequest entity
  • the entity is being validated
  • if it is not valid we are done here, no rubbish data gets pushed further of this point
  • if the data is valid it is passed to the service to do the business logic
  • service gets to work only with a valid, trusted core domain entity

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store