Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Personally I’m not a fan of Go’s default zero-initialisation. I’ve seen many bugs caused by adding a new field, forgetting to update constructors to intialise these fields to “non-zero” values which caused bugs. I prefer Rust’s approach where one has to be explicit.

That being said it’s way less complex than C++’s rules and that’s welcomef.



I spent a year and a half writing go code, and I found that it promised simplicity but there an endless number of these kinds of issues where it boils down to "well don't make that mistake".


It turns out that a lot of the complexity of modern programming languages come from the language designers trying to make misaked harder.

If you want to simplyfing by synthesising decades of accumulated knowledge into a coherent language, or to remove depreciated ideas (instead of the evolved spaghetti you get by decades of updating a language) then fine. If your approach to simplicity is to just not include the complexity, you will soon disciplinary that the complexity was there for a reason.


The problem you are describing in Go is rarely a problem in C++. In my experience, a mature code base rarely has things with default constructors, so adding a new field will cause the compiler to complain there's no default constructor for what you added, therefore avoiding this bug. Primitive types like `int` usually have a wrapper around them to clarify what kind of integers, and same with standard library containers like vector.

However I can't help but think that maybe I'm just so fortunate to be able to work in a nice code base optimized for developer productivity like this. C++ is really a nice language for experts.


Why would you have a wrapper around every primitive/standard library type?


Type safety.

Compare `int albumId, songId;` versus `AlbumId albumId; SongId songId;`. The former two variables can be assigned to each other causing potential bug and confusion. The latter two will not. Once you have a basic wrapper for integers, further wrappers are just a one-liner so why not. And also in practice making the type more meaningful leads you to shorter variable names because the information is already expressed in types.


FWIW there is a linter that enforces explicit struct field initialization.


Haven't written Go in a long time, but I do remember being bit by this.


Yea this can be problematic if you don’t have sum types, it’s hard to enforce correct typing while also having correct default / uninitialized values.


Wouldn’t it just be considered bad practice to add a field and not initialize it? That feels strongly like something a code review is intended to catch.


It’s easy to miss this in large codebases. Having to check every single struct initalisation whenever a field is added is not practical. Some folks have mentioned that linters exist to catch implicit initialisation but I would argue this shouldn’t require a 3rd party project which is completely opt-in to install and run.


All bugs are considered bad practice, yet they keep happening :P


You can always use exhaustruct https://github.com/GaijinEntertainment/go-exhaustruct

to enforce all fields initialized.

If you care, the linter is there, so this is more of a skill issue.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: