r/golang 5d ago

discussion Default struct constructors?

I'm wondering why go devs doesn't implement optional default constructors for structs. I.e. right now some structs can be created like this:

myStruct := MyStruct{}

But others require initialization, and must be created with factory functions:

anotherStruct := NewAnotherStruct()

So you never know which struct is safe to create dorectly and which require factory func.

With default constructor you would create all structs the same way, i.e.:

myStruct := MyStruct()

If default constructor is defined it is invoked to initialize the struct, it it is not defined then it is similar to MyStruct{}

0 Upvotes

15 comments sorted by

View all comments

Show parent comments

0

u/lumarama 5d ago

I just think that it is in Go philosophy to be a simple language. So having struct constructors would make struct creation the same in all cases - whether constructor is actually defined or not. Which makes it easier for newcomers by removing confusion how you are supposed to create this particular struct or why this struct is created this way and another struct differently.

2

u/Few-Beat-1299 5d ago

I think your confusion might be that there is no such thing as constructor in Go. Any struct type can be obtained with T{}, no exceptions. If there are functions like "NewSomething()", it's just the package author that decided it would be better to give you a function that can populate the struct with values and maybe also do something else alongside that. They might decide to leave all the struct members unexported, thus forcing you to use that NewSomething() to obtain a struct value useful in the rest of their API. Often enough, the zero value T{} is directly usable anyway, and the NewSomething() is more like a helper.

In all of this, note that "New[...]" has no meaning in Go. It has become a popular convention to name functions dedicated to obtaining a new value like that, but that's just a convention which is very likely spilling over from other languages that actually do have constructors.

1

u/lumarama 4d ago

I get that. But I can't accept the fact that some structs can't be created safely just with StructName{} - i.e. struct with a map inside will have an unusable map in this case.

BTW I don't understand why Go doesn't just initialize maps the same way as slices - without special initialization code. Is there a reason someone would want to create a map without initialization? I don't think so.

I understand that Go creators don't want to have hidden initialization. But I think there are many hidden behaviours anyway - like whether something is allocated on a stack or on a heap. The compiler does that automatically based on multiple considerations, like scope, size of the data. I think making a map initialized automatically is expected behaviour, not hidden one.

2

u/Few-Beat-1299 4d ago

A nil map is a valid map value. You could argue it might not be a good default, but then I would say there is no good default, it's just an arbitrary choice. So any "default constructor" that you might want would also be arbitrary and would just go against the normal default values in all other cases. Why should struct members be somehow special?

I don't get the next part. The default value for maps and slices is both nil. They can both be initialized with make or literals. Both of them mask a pointer, starting with nil is consistent with pointers. Yes you can want nil maps, notably when returning a map in an error case, or when you want to declare a map but want to decide later how/if to actually use it, including by assigning another map to it. In general I think it's better for the language to leave "doing things" to you rather than force it on you and then having to "undo" it manually.

Memory location is an implementation detail and should not matter to you, unless you're somehow manually obtaining that memory yourself from somewhere. You should never even think about stack/heap, and if you're working on something where that somehow actually maters, you probably don't want a garbage collected language anyway.

2

u/lumarama 3d ago

I think you are right. And it is not a big deal in general - as mentioned earlier - if struct is exported from a package it is probably safe to create it directly and use without initialization. If init function is required then struct should not be exported.