-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: Go 2: allow pointer types to be receiver base types in method declarations #48592
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
Comments
I found some more discussion that is relevant to this proposal. The Go Wiki the Rationals page has a section on pointer receivers that provides a similar justification for why pointer receivers are not supported:
I think this justification has the same problem as the similar but different justification that I included in this issues first comment/description. This is demonstrated with the below code. Because type T int
type P *T
var t T = 0
var p P = &t
fmt.Printf("%T\n", p)
fmt.Printf("%T\n", *p)
Ref: https://play.golang.org/p/G6TIyJQVB2g Other variations are also deterministic, such as fmt.Printf("%T\n", &p)
|
I agree that it is possible to define rules to make this work without ambiguity. But I think the result will be subtle and difficult to understand. It will require a clear grasp of the exact type of different expressions, and a clear understanding of the exact rules. Given that, and the fact that we have lived with the current rules for some time, what is the compelling reason for making this change? It seems possible to write the initial example using a struct with a pointer field and adding methods to the struct. This may require a bit more code in some places, but the advantage of that code is that it makes clear what is happening, and does not require the reader to understand the types and the rules. Having different marshaling for a type and a pointer to a type is confusing; introducing a different type to clarify matters seems like a good idea even if it requires writing a little more code. |
The counterintuitive quality of pointer types for me is that you can dereference a pointer type I don't think this proposal defines new rules that are counterintuitive, because it is valid to create a pointer type I do think this proposal will create new instances where this counterintuitive quality shows up, which could be a problem. There are two instances I can think of:
Both of these situations seem like they affect readability too greatly.
The compelling reason was to be able to write parsers that map directly onto types defined in other forms, such as XDR, where types can be pointer types. Using a struct as you say is definitely valid alternative. The specific library this proposal would benefit supports marshaling/unmarshaling both by using reflection and by using generated code. The reflection marshaler can easily support the pointer type because it needs no functions on the type, it only needs to be able to inspect the type, and its fields in the case of a struct or its underlying type. The code generator on the other hand needs to add functions to the pointer type. My dilemma is that while introducing a struct with fields in place of the pointer type will work in the code generated case, it will break the reflection based marshaler because the reflection based marshaler can no longer identify that the type is a pointer type, since the type is now a struct that wraps a pointer. I realize this isn't an insurmountable problem, I'm just detailing it here for the full picture. @ianlancetaylor Thanks. I agree with your comments. 👍🏻 |
Based on the discussion above, this is a likely decline. Leaving open for four weeks for final comments. |
No further comments. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Define a type that is a pointer to another type, and define methods for that type, so that type can be marshaled differently to include information about the optional quality of the pointer.
Example: https://github.com/stellar/go/blob/e24fae34b9166cc61bb9e6c4645eaabff844768b/xdr/xdr_generated.go#L1620
What did you expect to see?
I expected
go build
to suceed at compiling.What did you see instead?
Discussion
This behavior appears to be consistent with the specification that states:
There is also prior discussion on this topic on the golang-nuts mailing list that points out why this behavior is this way.
Ref: https://groups.google.com/g/golang-nuts/c/qf76N-uDcHA
However, after viewing code running in Go 1.17.1 today the reason that was given for why these types cannot be receivers is less clear. The prior conversation suggests we don't have a rule for what type
&v
is, however&v
is possible today and so we can write code that tells us what that rule is.For example, the output of the following code tells us what the rule is:
Ref: https://play.golang.org/p/YdYlHDub0eg
The output of the above code is pretty clear that
&i
is always*I
and neverP
, therefore in the example on the mailing list&v
is always*I
, therefore(&v).Get()
should also always callI.Get
since according to the specification:Being able to define types that are pointer types would make defining parsers for nested optional values simpler, because it would remove the need to wrap those nested types in a struct.
The proposal is support for pointer types to be a receiver base type in method declarations.
The specification would be changed from:
To:
Proposal template
Would you consider yourself a novice, intermediate, or experienced Go programmer?
Experienced
What other languages do you have experience with?
Java, Ruby, C#, C, JavaScript
Would this change make Go easier or harder to learn, and why?
Neither.
Has this idea, or one like it, been proposed before? If so, how does this proposal differ?
See discussion on the mailing list above.
Who does this proposal help, and why?
People building mashalers with nested optional types.
What is the proposed change?
See above.
Please describe as precisely as possible the change to the language.
See above.
What would change in the language spec?
The definition
Please also describe the change informally, as in a class teaching Go.
See above.
Is this change backward compatible?
Yes
Show example code before and after the change.
See above.
What is the cost of this proposal? (Every language change has a cost).
Likely none.
Insignificant.
Insignificant.
Can you describe a possible implementation?
See above.
No. But I can take a stab at contributing it.
How would the language spec change?
See above.
Orthogonality: how does this change interact or overlap with existing features?
Not sure.
Is the goal of this change a performance improvement?
No.
Does this affect error handling?
No.
Is this about generics?
No.
The text was updated successfully, but these errors were encountered: