# Proposal: Address operator for basic literals and bool literals Currently in Go, the address operator can only be applied to an addressable element (i.e. a variable, pointer indirection, slice indexing, addressable struct field). However, if you are using literals with numeric, string, or bool types, the address operator is not supported. This usually forces an intermediate variable assignments so pointer values can be accessed. This proposal is to introduce support for the address operator to be applied to basic type literals. ## Motivation One common convention often used in Go is the use of pointer values to differentiate between zero-value and omitted values. This is especially true in data serialization frameworks that use pointers to encode optional values. For instance, let us assume the use of an RPC framework with the following type where field `Name` is required while the others are optional: ```go type Task struct{ Name string Desc *string Active *bool Duration *float64 ... } ``` Initializing a value of type `Task` would require an intermediate variable assignment for each field with a pointer type as shown below: ```go active := true dur := 50.12 t := Task{ Name: "start", Active: &active, Duration: &dur, ... } ``` While the example looks simple and manageable, imagine a scenario where you need to initialize a dozen or more fields (in a test function for instance). This means you would need to create dozens of intermediate variables simply to access their pointer values. ### Workaround 1 One common workaround, to avoid the intermediate variable step, is to create a helper package with functions whose only purpose is to return value addresses as shown: ```go t := Task{ Name: "start", Desc: StringPtr("Starter task"), Active: BoolPtr(true), Duration: Float64Ptr(50.12), ... } ... func StringPtr(v string) *string { return &v } func Float64Ptr(v float64) *float64 { return &v } func BoolPtr(v bool) *bool { return &v } // and so on ... ``` ### Workaround 2 In an other workaround, composite types are used to box their respective basic types as shown in the snippet below: ```go type String struct {Value string} type Float64 struct{Value float64} type Bool struct{Value bool} ... type Task struct{ Name string Desc *String Active *Bool Duration *Float64 ... } ... t := Task{ Name: "start", Desc: &String{"Starter task"}, Active: &Bool{true}, Duration: &Float64{50.12}, ... } ``` Instead of intermediate assignments, this approach creates intermediate composite types for the sole convenience of automatically returning pointer values using the address operator. ## Proposal As mentioned in the previous section, the address operator can be applied to composite type literals to automatically return the address of their respective values as illustrated below: ```go 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 document proposes to extend this mechanism to 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: ``` "&" BasicType | bool "{" BasicLit | bool_lit"}" BasicType = ints | floats | imaginary | string ints = uint | uint8 | uint16 | ... | int | int8 | ... | rune floats = float32 | float64 BasicLit = int_lit | float_list | imaginary_lit | string_lit ``` The following shows examples of how the address operator would be applied to basic and boolean literal values to automatically return their respective addresses: ```go &int{12345} &uint64{1244} &byte{123} &bool{true} &string{"Hello"} type myT uint16 &myT{12} type myB = string &myB{"World!"} ``` ### Putting it all together The proposal would solve the initial problems outlined earlier by eliminating the need for intermediate assignments or boxed values as shown in the following: ```go 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}, } ``` Again, without this proposed change, the previous literal would require intermediate assignments as shown below: ```go 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, } ```