Description
Proposal
Add a new operator (?.) to support safe navigation.
Example
package main
type a struct {
b *b
}
type b struct {
c int
}
Current Behavior
Navigation across pointer of nil value causes runtime panic.
func main() {
x := a{&b{1}}
y := a{}
println(x.b.c)
println(y.b.c)
}
x.b.c
evaluates to 1
y.b.c
panics
1
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x45db4c]
goroutine 1 [running]:
main.main()
/tmp/sandbox869110152/prog.go:16 +0x6c
Proposed Behavior
Safe navigation across pointer of nil value evaluates to nil value of same type as target property.
func main() {
x := a{&b{1}}
y := a{}
println(x.b?.c)
println(y.b?.c)
}
x.b?.c
evaluates to 1
y.b?.c
evaluates to 0 (nil value of type similar to c
)
1
0
Reasoning
Null property traversal is a common cause of runtime panic. Frequently developers must disrupt the flow of their program by adding nil
checks in order to reproduce the behavior of a safe navigation operator. These nil checks add to the maintenance cost of the program by making the code less readable and introduce new opportunities for error.
Current idiom
func (a *a) getC() int {
if a.b == nil {
return 0
}
return a.b.c
}
Proposed idiom
func (a *a) getC() int {
return a.b?.c
}
Similar features in other languages
See https://en.wikipedia.org/wiki/Safe_navigation_operator
Also known as
- Optional chaining operator
- Safe call operator
- Null-conditional operator
Go 2 language change template
-
Would you consider yourself a novice, intermediate, or experienced Go programmer?
Experienced -
What other languages do you have experience with?
PHP, Javascript, Java, TCL, Bash, Actionscript, Erlang, Python, C++ -
Would this change make Go easier or harder to learn, and why?
Adds one more operator to learn which should feel familiar to people having experience with analogous operators in other languages popular among Gophers (C#, Ruby, Python, PHP, Typescript, Rust, Scala). -
Has this idea, or one like it, been proposed before?
Not found in github issues. One slightly similar golang-nuts post from 2013. -
If so, how does this proposal differ?
Previous discussion appears to relate specifically to null pointer receiver methods rather than nested struct traversal or command chaining. -
Who does this proposal help, and why?
Developers moving to Go from languages that already support safe navigation. -
What is the proposed change?
Add operator?.
(see above). -
Please describe as precisely as possible the change to the language.
Add tokenQUES_PERIOD = "?."
. Modify selector expression or add new safe selector expression to achieve behavior described above. Not valid on left hand side. -
What would change in the language spec?
Expansion of selector expression definition and operator list -
Please also describe the change informally, as in a class teaching Go.
The safe navigation operator?.
can be used to short circuit property traversal when a nil pointer is encountered, avoiding panic. -
Is this change backward compatible?
Yes. -
What is the cost of this proposal? (Every language change has a cost).
Higher maintenance costs due to increase in number of operators and more complex selector expression code. -
How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
Possibly several. Depending on implementation, maybe none. -
What is the compile time cost?
Presumably low -
What is the run time cost?
Presumably low -
Can you describe a possible implementation?
Add new tokenQUES_PERIOD = "?."
. Then either modifyast.SelectorExpr
or add newast.SafeSelectorExpr
-
Do you have a prototype? (This is not required.)
In development -
How would the language spec change?
Expansion of selector expression definition and operator list -
Orthogonality: how does this change interact or overlap with existing features?
Syntactically identical with.
operator in selector expressions except where the value of the expression is nil (where the.
operator would panic) -
Is the goal of this change a performance improvement?
No. -
Does this affect error handling?
No. -
Is this about generics?
No.