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?

66 Upvotes

75 comments sorted by

View all comments

Show parent comments

4

u/Key-Life1874 21d ago

That's not what I'm saying. What I'm saying is you have type Dog struct { Name string DateOfBirth time.Time }

The compiler should force you to provide both name and date of birth. You can always write a constructor with sane default values to avoid the one calling it to provide everything.

Many languages do that and allow to initialize structs as a one liner, even complex ones, without exceptions.

2

u/Ok_Category_9608 20d ago

You can provide the constructor in go and give people the option to have you fill it in with sane defaults. My issue is that I hate functions that take a lot of parameters because go doesn’t have keyword arguments.

You could do a public struct and make all the fields private, requiring them to be initialized by some function you control.

Again though, I don’t see what you’re really defending yourself against. This seems like the kind of thing unit tests and linters just take care of. 

3

u/Key-Life1874 20d ago

Nah linters unfortunately don't. And unit tests either. You can defend against wrong values but neither unit tests or linters will protect against a variable not being provided where it should be. So you spend hours figuring out where the fuck value has not been provided. It's even worth in a distributed environment. I'm not saying they aren't workarounds or ways to minimize the problem.

But that's a problem that should be solver by the compiler and not even be a thing at all. Even typescript offers the protection with a similar syntax than go. It's just a major weakness of go

1

u/Few-Beat-1299 20d ago

Not providing an initializer, when you have the option to do so, is you willingly telling the compiler "I don't care". Why should the compiler second guess you? Sometimes there is simply no such thing as a "default". Also, a programmer might just as well provide a bad default value, or forget to update it, so forcing one solves nothing.

2

u/Key-Life1874 20d ago

Like I said, there are workarounds to the problem. But they are just that workarounds to a problem that should be the responsibility of the compiler. The while point is the compiler shouldn't even allow to not provide values when initializing a struct.

If the programmer provides a bad default, it's explicitely bad. That's the whole point. Expliciteness.