-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: Go 2: default initializers for types #32076
Comments
There are lots of cases that would have to be handled to make this consistent.
? At an even deeper level, what happens in this case:
This is a data race, of course, so as far as the spec goes we're in uncharted territory. But goroutine 2 might very well observe p.X == 0, a mysterious out-of-the-blue value that objects of type Foo should never contain. This isn't a problem today because all objects are zero-initialized. The GC can zero everything at sweep time and synchronize with all threads so they are guaranteed to see that zeroing. No reader can ever see the contents of the previous life of a recycled object. In contrast, in this proposal there's no cheap way to do that global synchronization because the contents required to initialize the memory are not known at sweep time. |
I think that the fact that everything is zero-initialised in Go is a useful feature, which leads to the Go idiom of making sure that the zero value of your struct is actually useful. That's an important idiom we should stick to, so that's why I don't like this proposal very much. Also, it does nothing that can't be done using a constructor function. Therefore I don't think we need a new language feature for this. |
@randall77 and @beoran, the proposal doesn't nullify the zero-value aspect of golang. This seems to be a proposal on extending initialization for a default value. If that is the case, @randall77, you would not see any difference in the |
To address issues about consistency: The proposal ideally would change what the "zero value" (I guess now "default value"?) of a type would be.
That's fairly intuitive. I don't have opinions one way or another about this. Unfortunately it allows for this...
This is gross. However, the 1st syntax in the proposal would not allow for this since only structs can have default values in that scenario, but it would also mean that all non-structs would not be able to have default values. Regarding data races, I unfortunately can't think of a way to make it thread-safe off the top of my head. The only way I could think of is building mutexes into certain variable accesses, and that's just... bad.
Really all this proposal does is make the "zero value" (aka default value) easier to use. What this proposal does is make it much easier to make the default value of a type to be useful, rather than making developers jump through hoops to make the zero value of their type useful. However, it does make the default value of a type less predictable, it forces you to look at the documentation rather than being able to assume what it is, which is not good.
I was about to say that this was factually correct but missing the point, but it actually isn't factually correct. Constructor functions are unable to control what is emitted from I'm not super fond of this proposal myself, and the data race issue doesn't help my take on it. It's just an offshoot of another proposal, and I wouldn't personally mind it in the language |
@randall77, racy Go programs can already observe invalid values, such as interfaces whose values are not actually of the associated type. And, of course, nothing prevents the allocator or collector from zeroing unused memory and anticipating zeroed values in normally-nonzero fields of allocated objects. |
Given the problems pointed out by @randall77 and the fact that we rely heavily on zero initialization in Go programs, this proposal seems to introduce more problems than it solves. For instance, a reader of a program could not rely anymore on the fact that a composite literal |
Default Initializers
I'm not sure what reminded me of this idea. This is an offshoot of #28939 which was closed, however there was still discussion about default initializers which shortly died off. I figured I would create a quick proposal about how this would work.
Goal
The goal of default initializers is to allow types to have default state when initialized. This helps reduce boilerplate code at both the declaration site and the call site.
Declaration Syntax
There are two syntaxes that will be brought up.
Syntax 1:
Syntax 2:
type Bar uint default 5
Allows for default values for non-struct valuesCall Site
The reason that
Foo{Y:10}
resolves toFoo{5,10}
and notFoo{0,10}
is for consistent behavior with unexported variables. Also this prevents people from trying to be "clever" by writing code that is less readable, and prevents subtle bugs from changingFoo{}
toFoo{Y:10}
.Note - the following two functions remain equivalent, just as they are in current Go:
Footnote
I'm personally not sure what to think about this proposal. I mainly made it since it's been discussed before but there was no proposal made for it yet. I know some people would like it since it reduces boilerplate code, while others would say it adds bloat to the language and makes the call-site less predictable.
The text was updated successfully, but these errors were encountered: