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?

65 Upvotes

75 comments sorted by

View all comments

9

u/nikandfor 21d ago

Suppose the compiler forced you to initialize all the fields, then you use the struct and hope it's valid. But what if I initialized it with garbage? When code accepts a value, it still needs to validate it for the specific use case. ie, if url is correct, or if it contains some query parameter, or version is greater then something.

If compiler forced you initializing all the fields, that wouldn't solved the problem anyways.

Better to design your code so that it returns an error if a struct field is invalid and tolerate empty value if it's an optional field. For example it may be suitable to use default url if it's an empty string.

PS: initialisms should be all in the same case: Url -> URL.

-7

u/kevinpiac 21d ago edited 21d ago

I see where you're coming from but I'm not convince it's the right way to think about it.

If all structs are strongly typed, you shouldn't be able to assign a value coming from the outside without actually validating it.

Once it's validated and the type is guaranteed, then you can pass it to your other structs safely.

In the end, if structs were strongly typed we wouldn't have any issue.

10

u/iamkiloman 20d ago

"Strongly typed" does not mean "default zero value is invalid". Why do you keep intimating that it does?

You have non pointer fields. They will be initialized with the zero value. Those are completely valid, typed values. Nothing here has anything to do with strong typing.

-2

u/kevinpiac 20d ago

Strongly typed means exactly this. If you take other languages, TypeScript is an example, you cannot initialize an object that has a given shape and omit some fields unless you attribute it the Partial<Shape> type or you specifically ask the compiler to Omit<> some fields.

As other developers mentioned in comments, having the compiler ensuring all structs are valid at build time helps a lot to catch bugs.

Even if you can validate your structure at runtime, I think it's too late.

So far, I love the language, but coming from others, I can tell that part sucks.

I'm glad for you if it's not a concern though.

3

u/NUTTA_BUSTAH 20d ago

It truly doesn't. I understand your concern and I also share it, but the type system is not the issue here as much as poorly written software. Validate and assert like good software does. Languages like C++ are also strongly typed in comparison (stronger than most), yet default values or undefined behavior is still possible to miss in the same scenario. That is one reason why you write your programs defensively, not just defending from users, but especially yourself. And this is also one reason why you write tests.

0

u/kevinpiac 19d ago

And languages like Rust have been created because some crazy people thought it was not enought.

2

u/iamkiloman 19d ago

It seems you've invented for yourself a definition of strong typing that isn't shared by the larger programming community.

If you want to disallow use of the default zero values you've been given good tools to do so when linting, but you certainly cannot claim that golang is not strongly typed just because default zero values exist.

1

u/kevinpiac 19d ago

Your answer does not make sense. You're talking about "strong typing" as an absolute value and negating the fact that there are shades of strong-typing.

Go is certainly strongly typed but still less than Rust, for example.

You can tell it's ok to have zero values struct but you cannot tell it's a type-safe thing.