iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
💻

Ambiguous Braces

に公開

This topic came up in the "Go Programming Language" community on Twitter, and since it was quite interesting, I'm writing it down as a memo.

It's slightly different from what was shared in the community, but here's the starting point of the code.

prog.go
package main

import "fmt"

type person struct {
    name string
}

func main() {
    if p := person{name: "alice"}; true {
        fmt.Println("hello", p.name)
    }
}

Setting aside the fact that the condition in the if statement is always true, it looks like a harmless piece of code at first glance. However, when you try to run it:

./prog.go:10:7: syntax error: cannot use p := person as value
./prog.go:11:31: syntax error: unexpected newline in composite literal; possibly missing comma or }

You get a compilation error like this. I didn't understand it at first either, but it seems the braces of the if { ... } statement and the braces of the struct literal person{ ... } are being confused. It's very Go-like to safely treat this ambiguity in parsing as a "compilation error" rather than arbitrarily favoring one interpretation over the other (lol)

Actually, this point is explicitly stated in the language specification.

A parsing ambiguity arises when a composite literal using the TypeName form of the LiteralType appears as an operand between the keyword and the opening brace of the block of an "if", "for", or "switch" statement, and the composite literal is not enclosed in parentheses, square brackets, or curly braces. In this rare case, the opening brace of the literal is erroneously parsed as the one introducing the block of statements. To resolve the ambiguity, the composite literal must appear within parentheses.

if x == (T{a,b,c}[i]) { … }
if (x == T{a,b,c}[i]) { … }

(via “The Go Programming Language Specification - The Go Programming Language”)

Therefore, in this case, it seems you just need to wrap the struct literal description in parentheses ( ... ), like this:

if p := (person{name: "alice"}); true { ... }

I've learned something today.

GitHubで編集を提案

Discussion