The use of &T{} for composite literals is strange, and in particular inconsistent with the way you write a type. Consider the following code:
foo := struct{
m map[int]string
a [10]int
sl []string
st struct{}
p *struct{}
}{
m: map[int]string{},
a: [10]int{},
sl: []string{},
st: struct{},
p: &struct{},
}
p is the only member for which the type declared does not match the type used in the composite literal. The logical fix is to make a composite literal of type *T mean a composite literal to a pointer to a new value of type T initialized from the literal, in place of &T.
This is probably incompatible with #20446.
foo := struct{
p *int
}{
p: &i,
}
&T have two meanings.
If want to create new int value and get pointer of the value, we can't do it without new builtin. (ex: new(int)) If you mean a := *int or a := *int{} should have meaning to get pointer of new value, compiler will have to look backward literals like C. Then compiler will be slow.
But then what's the dereference operator? I think the most logical thing would be to use & in the type signature of pointers, so that if you have a var i int then &i's type is &int and the type signature and literal expression also match. And there is a historical precedent (in C++) for &T being a pointer to T.
But I don't think it's worth it.
If you are to replace &T{} with *T{}, I would be confused. I am used to seeing the _pointer/deref_ (*) and the _address of_ (&) operators. I think Go's usage of them has been consistent with other C-family programming languages. If you are to replace those, you will create unnecessary confusion to many people, considering the popularity of C/C++ and the people's familiarity with them.
I don't agree with this proposal.
Note that in your example, the lines
st: struct{},
p: &struct{},
must today be written as
st: struct{}{},
p: &struct{}{},
(two pairs of braces each).
I suspect that, to avoid a parsing ambiguity, the latter case would need to be written as
p: (*struct{}){},
but today that syntax is rejected by the compiler (https://play.golang.org/p/6GxjWrCfgN).
Also note that under https://github.com/golang/go/issues/12854 they could be written even more uniformly:
foo := struct{
m map[int]string
a [10]int
sl []string
st struct{}
p *struct{}
}{
m: {},
a: {},
sl: {},
st: {},
p: {},
}
This idea was discussed during the development of Go 1 (that is, as a change from the earlier versions of Go to the standarized Go 1), but was rejected at that time.
It is important to understand that & and * aren't interchangeable tokens, but rather opposite and complementary. & means "take the address of value", and * means "get the value at address". From this, it makes no logical sense to say *T{}, because you would wind up reading this as "take the value at the address T{}", and then you realize T{} isn't an address and so the statement makes no sense.
Perhaps memorizing this would help you stop confusing &T{} and *T{} as much (as you said in the proposal for #20446).
This also explains @cznic's comment: what if you want to point to a variable that already exists in a composite literal? (The line that is missing from their comment is var i int.)
@andlabs The * operator is distinct from the * type-constructor. The & operator is dual to the * operator, but the * type-constructor has no dual.
&T{} is the _expression_ "address of a literal of type T", but *T is the _type_ "pointer to T". The * _operator_ is not involved in this proposal in any visible way.
@bcmills Yes, but is &T{} in the context of an assignment or composite literal also not an expression? Given what you said, another way to say what I was trying to say is that this proposal confuses and conflates the * type-constructor with the * operator, if that makes more sense.
The way I read this proposal, it is that &T{} should be read as "the address of a literal of type T", and *T{} should be read as "a literal of type *T". (The latter is currently rejected as a syntax error.)
Ah, yes, that is different. If we do expand composite literals to all types (a more general version of your reading of the proposal), by current rules it would have to be (*T){...}.
Isn't the current situation due to ambiguity between the binary * operator? A potential solution would be to drop * for indirection, but that seems to be beyond the scope of the current proposal phase for Go 2?
There doesn't appear to be strong support for this, and you say yourself it would be incompatible with #20446 / #9097. It was also discussed years ago and rejected. Closing.
Most helpful comment
If you are to replace &T{} with *T{}, I would be confused. I am used to seeing the _pointer/deref_ (*) and the _address of_ (&) operators. I think Go's usage of them has been consistent with other C-family programming languages. If you are to replace those, you will create unnecessary confusion to many people, considering the popularity of C/C++ and the people's familiarity with them.
I don't agree with this proposal.