Skip to content

proposal: Go 2: allow taking address of const literals #51066

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

Closed
YairHalberstadt opened this issue Feb 8, 2022 · 1 comment
Closed

proposal: Go 2: allow taking address of const literals #51066

YairHalberstadt opened this issue Feb 8, 2022 · 1 comment

Comments

@YairHalberstadt
Copy link

YairHalberstadt commented Feb 8, 2022

Author background

  • Would you consider yourself a novice, intermediate, or experienced Go programmer? intermediate
  • What other languages do you have experience with? csharp, scala, python

Related proposals

  • Has this idea, or one like it, been proposed before? I haven't seen one, but it's difficult to search for proposals here.
  • Does this affect error handling? No.
  • Is this about generics? No.

Proposal

  • What is the proposed change? Allow taking the address of const literals
  • Who does this proposal help, and why?

Anyone assigning a const to a field which takes a pointer.

Currently when creating large composite literals, where one of the fields is a pointer to a bool, string, int etc. which you want to assign a constant literal to it, you have to assign the constant to a temp before you create the literal, and then take the address of the temp.

This is purely busywork, and is inconsistent with composite literals where you can take the address directly. It also makes it harder to see everything in one go as the data is spread out between the temps and the composite literal.

As an example, this is common in k8s CRDs -e.g.

trueVar := true
v1.PodSpec {
    Containers: [] v1.Container {
        {
            Name: "my-container",
            Image: "my-image",
            Env: [] v1.EnvVar {
                // lot's of env vars
                // ...
                {
                    Name: "SOME_ENV",
                    ValueFrom: & v1.EnvVarSource {
                        ConfigMapKeyRef: & v1.ConfigMapKeySelector {
                            LocalObjectReference: & v1.LocalObjectReference { Name: myConfigMap.Name },
                            Key: "someKey",
                            Optional: &trueVar,
                        }
                    },
                },
            },
        },
    },
}
  • Please describe as precisely as possible the change to the language.

Allow taking the address of constants literals.

So this would be allowed:

x := &5

And is semantically equivalent to

temp := 5
x := &temp

But this wouldn't:

const c = 5
x := &c

*x = 4 // Might assume that c is now &4, but it isn't so best just to disallow this.

This is similar to how it's already possible to take the address of other literals:

x := &[]*MyStruct{
    &MyStruct{ Field: &map[string]string{} }
}

which is equivalent to:

temp1 := map[string]string{}
temp2 := MyStruct{ Field: &temp1 }
temp3 = []*MyStruct{
    &temp2
}
x := &temp3
  • What would change in the language spec?

https://go.dev/ref/spec#Address_operators would be updated as follows:

From

The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.

To

The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal, integer literal, floating-point literal, imaginary literal, rune literal, string literal and the predeclared constant identifiers true, false, and iota.

  • Please also describe the change informally, as in a class teaching Go.

You can now do this

x := &4
y := &"some-string"
z := SomeStruct{
   Field: &true
}

whereas previously you would get a confusing error.

  • Is this change backward compatible?
    Yes
  • Orthogonality: how does this change interact or overlap with existing features? N/A
  • Is the goal of this change a performance improvement? No

Costs

  • Would this change make Go easier or harder to learn, and why? Easier, as what should intuitively work will just work.
  • What is the cost of this proposal? (Every language change has a cost). The cost to implement in the compiler and update the spec, but should mostly be relatively straightforward.
  • How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected? None that I'm aware of.
  • What is the compile time cost? Practically nonexistent.
  • What is the run time cost? None.
  • Can you describe a possible implementation? Assign to a temp, and then take the address of the temp.
  • Do you have a prototype? (This is not required.) No.
@gopherbot gopherbot added this to the Proposal milestone Feb 8, 2022
@randall77
Copy link
Contributor

Dup of #45624

@golang golang locked and limited conversation to collaborators Feb 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants