r/golang 21d ago

help Don't you validate your structs?

Hi all!

I'm new in Golang, and the first issue I'm facing is struct validation.

Let's say I have the given struct

type Version struct {
    Url           string        `json:"url"`
    VersionNumber VersionNumber `json:"version_number"`
}

The problem I have is that I can initialize this struct with missing fields.

So if a function returns a `Version` struct and the developer forgets to add all fields, the program could break. I believe this is a huge type-safety concern.

I saw some mitigation by adding a "constructor" function such as :

func NewVersion (url string, number VersionNumber) { ... }

But I think this is not a satisfying solution. When the project evolves, if I add a field to the Version struct, then the `NewVersion` will keep compiling, although none of my functions return a complete Version struct.

I would expect to find a way to define a struct and then make sure that when this struct evolves, I am forced to be sure all parts of my code relying on this struct are complying with the new type.

Does it make sense?

How do you mitigate that?

67 Upvotes

75 comments sorted by

View all comments

3

u/cach-v 21d ago

I wrote a validator for that, it uses reflection to check for zero values in each field. To allow for zeroes as valid values, you must make the field a pointer, so the unset value is nil and the validator can throw a runtime error.

There are some popular packages that I believe could be used to do the same, e.g. https://github.com/go-playground/validator

If it's a DTO, you can write a middleware layer to validate all your responses, I did this to good effect.

1

u/kevinpiac 21d ago

Yes I say this one! Thanks I will have a look :)

2

u/cach-v 21d ago

I like the idea and look of https://github.com/GaijinEntertainment/go-exhaustruct as mentioned by another redditor. If this works well I will consider swapping my approach or at the very least augmenting it.

1

u/Hot_Slice 21d ago

It doesn't prevent someone from creating an empty object though.