-
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: builtin/new: giving new the ability to call init when creating custom types #62240
Comments
For language change proposals, please fill out the template at https://go.googlesource.com/proposal/+/refs/heads/master/go2-language-changes.md . When you are done, please reply to the issue with Thanks! |
Hi @godcong, I do largely agree with and empathize with your problem statement: I've also seen developers try to instantiate types using composite literals instead of calling a provided "New" function, and then have strange things happen when they try to use the partially-initialized value. It's frustrating that the compiler cannot give direct feedback about such mistakes. I think your specific proposal has a challenge, though: it's already valid to declare a method named Unless we can find some way to show that it isn't a breaking change after all, I suspect the details of the proposed solution would need to change so that it's proposing to add something new to the language, rather than changing the meaning of something that's already valid. Edit: A further concern that occurred to me after further consideration is that if there is an existing method called Making that function callable from outside of the package indirectly using |
see previously #28939 |
Note that it is fundamentally impossible to prevent a user from creating a zero value of your type. For example, you can write var x T
s := make([]T, 1)
x := s[0]
m := map[bool]T{}
x := m[true]
ch := make(chan T)
close(ch)
x, _ := <-ch
var s []T
for cap(s) == len(s) {
s = append(s, *new(T))
}
x := s[:cap(s)][cap(s)-1] or any number of other ways. The property of any Go type having a zero value - and that zero value being represented entirely by 0 bits in memory - is a deliberate choice, deeply ingrained and assumed in the language. It's relied on for efficiency in a number of places as well (the examples above demonstrate how I'll also note that while I really don't see this happening, to be honest. |
Proposal TitleAutomatic Invocation of User-Defined init Method when Using new SummaryAutomatically invoke the init method of a user-defined type when creating an instance using the new keyword. MotivationIn the current version of Go language, when creating an instance of a user-defined type using the new keyword, the init method of that type is not automatically invoked. Detailed DesignWhen creating an instance of a user-defined type using the new keyword, the compiler will automatically invoke the init method of that type immediately after the instance is created. This ensures that the instance is properly initialized right after creation without the need for manual invocation of the init method by developers. Here is an example code demonstrating the usage of this feature: package main
import "fmt"
type MyStruct struct {
Name string
}
func (m *MyStruct) init() {
m.Name = "Initialized"
}
func main() {
instance := new(MyStruct)
fmt.Println(instance.Name) // Output: Initialized
} CompatibilityThe introduction of this language feature will not affect existing Go code, as it is an enhancement specifically for instances created using the new keyword. Existing code will continue to work as before. Open QuestionsThe introduction of this language feature may raise some discussions and questions, such as:
These questions will require further research and decision-making during the discussion and implementation process. |
When new has finished what it was doing, it calls |
It's simple to write a factory function that does exactly what you want. This proposal doesn't add new functionality that we don't have already, but introduces a number of difficulties as @Merovius mentions above. Also, the emoji voting is not in favor. Therefore, this is a likely decline. Leaving open for three weeks for final comments. |
No further comments. |
In most cases, we now have users creating a user-defined type in the following way.
You can see that the person who defined the type didn't want the value to be externally modified.
But in many cases, the user may create the type in the wrong way, as in the case of //wrong
and new is used very, very rarely in the creation of user-defined types.
Based on the above, I think we should enhance the functionality of new to make it true to its name.
Just as importing a package executes init, I think that when you create a struct, you should also execute the corresponding init method (if any).
It gives the struct the correct way to initialize, and allows the developer to correctly initialize some non-public values.
It also saves the developer from having to write a
New
function (which would become unnecessary).It looks like this
This allows any user to use new to create types correctly.
and it makes the behavior of go more consistent...
Unreasonable questions like the following can also be answered:
Why does import execute
init
but not callinit
anywhere else, shouldn'tinit
be called for all initializations?2023/09/05 Add
I envision that he should work correctly like
import
->init()
.When I create a type using
new()
, it try to call the methodinit()
.The
init
is an internal function, so it takes care of things that only the creator wants to have to do when the function is initialized.The text was updated successfully, but these errors were encountered: