-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: spec: add &T(v) to allocate variable of type T, set to v, and return address #9097
Comments
"px := new([]int, 1, 2, 3)" Ah, so it's meant to support even slices? But using a different syntax than a slice literal has ({[key:] value, ...})? But without the possibility to set len and cap? How it's supposed to handle maps? `pm := new(map[t]u, 1, 2, 3)`? What is the key and what is the value? Or map types, as an exception, do not qualify as a 'Type'? Etc. I think this all shows how much of a bad idea this proposal is. |
So for slices a list o values is used (#2) px := new([]int, 1, 2, 3) But for map types it uses a composite literal (#4) pmap := new(map[string]int, map[string]int{ "A": 1, "B": 2, }) Which case is the norm and which is the exception? Why not in the slice case write analogically px := new([]int, {1, 2, 3}) // ? It also supports the existing key: val thing px := new([]int, {1, 42: 2, 3}) IOW, we're back to the "why the ... "? If the proposal would be accepted, which I hope is not going to happen, I think that it would have to be new(T, optExpr) // 1 is a literal as is {1, 2, 3}, etc. Where optExpr is optional, similarly to make(T, optExpr1, optExpr2) // [0] BTW, please let's not forget - the best feature of Go is its lack of "features". [0]: http://golang.org/ref/spec#Making_slices_maps_and_channels |
#5 Sorry, i made a misstake. I only hope these two `new` type: func new(Type) *Type func new(Type, value Type) *Type Not include this `new` type: func new([]Type, values ...Type) *[]Type Beause it will cause this confused code: px := new([]int, []int{1}) px := new([]int, 1) // like new([]int, 1, 2, 3) Some examples: px := new(int) px := new(int, 123) px := new([]int) px := new([]int, []int{1, 2, 3}) px := new(map[string]int) px := new(map[string]int, map[string]int{ "A": 1, "B": 2, "C": 3, }) |
Here's a proposal witch should be related with this issue. I'd like you to review and make some comments. https://docs.google.com/document/d/111YaXFZeJbJ9DhOF69CvvFV49YTkUKpIRKiS42woMak/edit?usp=sharing |
See also #19966. |
I don't see why we need both For this kind of thing it's interesting to consider the type I think the proposal here should be to add to the language the expression |
It's not silly at all. It's painful enough, so |
@bcmills can you elaborate? I didn't think there was any "address of copy" syntax. |
@icholy, the syntax &(*x) today evaluates to the same value as It would be confusing for &(*x+1) to suddenly have a dramatically different aliasing behavior — changing from allocating a new value to aliasing an existing one — simply because the |
This would make my life easier and my code cleaner. There are libraries that use
|
I came here from #37302, and this really an annoyance in Go. Everyone is writing these small helper functions to transform a constant into a pointer, such as intPtr(v int) *int { return &v}, etc. These functions get copied around everywhere, they are even in the Go standard library! Mostly they are used for used in testing: e.g.: src/encoding/asn1/asn1_test.go, src/encoding/json/decode_test.go, etc, and the definition is often redundant, and even named differently. In stead of these functions, we could really use this &type() syntax to get rid of these little helper functions everywhere, even in the standard library. |
How do we move this proposal forward, either to decide for or against it? Specifically I'm referring to the As Ian summarized earlier:
(Separately we could consider What's the best way to follow through with the |
I don't see any clear consensus in the discussion above. Although the emoji voting on It's also worth considering that the generics design draft permits writing package addr
func P(type T)(v T) *T {
return &v
} which can then be used as p1 := addr.P(1) // p1 has type *int
p2 := addr.P(iint64(2)) // p2 has type *int64
p3 := addr.P("hi") // p3 has type *string
p4 := addr.P(time.Now()) // p4 has type *time.Time This has some advantages, in that it doesn't require a new language feature (well, doesn't require a language feature other than generics), and it doesn't require writing the type when that is not needed. So personally I would be inclined to wait until we have generics to see if an approach like that seems sufficient. |
That's reasonable thanks. I'm content to wait on that, assuming that generics design is going somewhere in the next couple of years. :-) |
@ianlancetaylor, you prefer a third syntax to create pointers?
That adds to the education/cognitive burden which is often raised re language proposals.
@griesemer any thoughts? |
@networkimprov As @ianlancetaylor also mentioned earlier, no clear consensus has emerged yet. I agree that it would be nice to resolve this but there's no urgency. I'd be happy to wait for a truly compelling solution or a strong reason to move forward with one of the existing suggestions. As far as I can tell, this is not blocking anything. And, just to be clear, adding a third syntax seems not a good plan. We want to make things simpler and clearer, not more complicated. |
I want to float another potential approach here. Given that taking the address of arbitrary expressions seems confusing based on the existing semantics, why don’t we reduce the scope and instead make two specific changes:
I think this covers most of the use-cases while requiring minimal language spec changes, and without introducing new potentially ambiguous cases. I also think the meaning of the syntax is easy to understand for a reader as it re-uses the & operator to create a pointer. The main disadvantage is that it may lead people to assume that &1 should work without the typecast, this can be solved by updating the compilation error you get to say “cannot take the address of 1. To take the address use an explicit cast: &int(1)” The main time that I want these operators to work is when I’m constructing an object literal and the object has pointer-valued fields (this happens mostly today when modeling SQL tables with NULL-able columns, but also in a a variety of APIs that distinguish between the absence and presence of a variable). As a new go programmer I used to create temporary variables, but I have since changed and have written a set of helper functions (similar to #38298) I decided against the following, because it seemed more complicated, but we could instead of 2. above, do: 2. extend the constant behavior so that & on a constant literal gives you a constant that has a default type of a pointer to the literal’s default type and which gets its definite type from the context in the same way constants do. That would allow i := &1 to set i to a I also decided against adding a pointers package (like the other proposal) because this change would work for any type (importantly for me time.Time) and also help beginners who are confused by why they can’t take the address of a return value (me included). And against trying to add another kind of optional syntax to go, pointer values are a good conceptual match for optionals and I don’t think we need more syntax for similar things. (It also seems like a go2 concern!) |
I came here from #42690 also same reason of @beoran problem. I wrote library that helps handle nil and non-nil value for a variable with homogenous type. However, it doesn't add significant benefit due to prohibition of implicit conversion. Thus, I should workaround code like this: myString := "Hello Gophers!"
myNullableString := nullable.NewString(&myString) instead of directly assign pointer as parameter like this myNullableString := nullable.NewString(&string("Hello Gophers!")) and speaking of simplicity, this approach is relatively simple than declaring "home variable" first. It's less line count and seems understandable for newbies. Moreover, I didn't see any syntax collision here with |
These ideas have been taken up again in the new proposal #45624. |
I'm going to close this issue in favor of #45624. |
The text was updated successfully, but these errors were encountered: