Skip to content

proposal: Address operator for basic and bool literals  #39085

Closed
@vladimirvivien

Description

@vladimirvivien

Currently in Go, the address operator (&) can only be applied to an addressable element (i.e. a variable, pointer indirection, slice indexing, addressable struct fields, and composite literals). However, if you are using numeric, string, or bool literals, the address operator is not supported. This usually forces some awkward workarounds that either use intermediate variables, or boxed values (basic literals wrapped in composite types), or helper functions that return pointers for their passed values.

Proposal

As mentioned earlier, the address operator can be applied to composite literals to automatically return the address of their respective values as illustrated below:

type myT struct{a string}
a := &myT{"A"}
x := &struct{a string; b int}{"A", 12}
y := &[]string{"A","B"}
z := &[1]int{2}

This proposal calls for extending this mechanism so that the address operator could also support numeric, string, and boolean literal operands. To minimize impact on the language, the proposal calls for the reuse of the same lexical format used for composite literals, mainly:

"&" basic_types | bool "{" BasicLit | BoolConstant"}"

The following shows examples of how the address operator would be applied to basic and boolean literal values to automatically return their respective addresses:

t := struct {
    f1 *int
    f2 *string
    f3 *float64
    f4 [2]*int64
    f5 *bool
}{
    f1: &int{12},
    f2: &string{"Hi!"},
    f3: &float64{3.14},
    f4: [2]*int64{&int64{44}, &int64{12}},
    f5: &bool{true},
}

By contrast, one of the ways to do the same thing today requires an intermediate set of variable assignments as shown below:

f1 := 12
f2 := "Hi!"
f3 := float64(3.14)
var a, b int64 = 44, 12
f5 := false

t := struct {
    f1 *int
    f2 *string
    f3 *float64
    f4 [2]*int64
    f5 *bool
}{
    f1: &f1,
    f2: &f2,
    f3: &f3,
    f4: [2]*int64{&a, &b},
    f5: &f5,
}

Another workaround uses a sort of type boxing that declares additional types that can wrap basic values inside corresponding struct values:

type Int struct{Value int}
type String struct {Value string}
type Float64 struct{Value float64}
type Int64 struct{Value int64}
type Bool struct{Value bool}
...
t := struct {
    f1 *Int
    f2 *String
    f3 *Float64
    f4 [2]*Int64
    f5 *Bool
}{
    f1: &Int{12},
    f2: &String{"Hi!"},
    f3: &Float64{3.14},
    f4: [2]*Int64{&Int64{44}, &Int64{12}},
    f5: &Bool{true},
}

Some codebase uses yet another workaround that define a set of additional helper functions to provide the convenience of returning the addresses of their passed values as shown:

func Int(v int) *int {return &v}
func String (v string) *string {return &v}
func Float64(v float64) *float64 {return &v}
func Int64(v int64) *int64 {return &v}
func Bool(v bool) *bool {return &v}

t := struct {
    f1 *int
    f2 *string
    f3 *float64
    f4 [2]*int64
    f5 *bool
}{
    f1: Int(12),
    f2: String("Hi!"),
    f3: Float64(3.14),
    f4: [2]*int64{Int64(44), Int64(12)},
    f5: &Bool(true),
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions