Composite literals

September 20, 2023

Earlier this year, near the beginning of this series on the Go spec, we went through literal representations of all of the basic types in Go: ints, strings, etc.

If this were an Intro to Go style book, the very next section would have been on composite literals. But it’s not. So we had to wait nearly 6 months to get to that topic… But here we are, at long last!

Composite literals

Composite literals construct new composite values each time they are evaluated. They consist of the type of the literal followed by a brace-bound list of elements. Each element may optionally be preceded by a corresponding key.

CompositeLit  = LiteralType LiteralValue .
LiteralType   = StructType | ArrayType | "[" "..." "]" ElementType |
                SliceType | MapType | TypeName [ TypeArgs ] .
LiteralValue  = "{" [ ElementList [ "," ] ] "}" .
ElementList   = KeyedElement { "," KeyedElement } .
KeyedElement  = [ Key ":" ] Element .
Key           = FieldName | Expression | LiteralValue .
FieldName     = identifier .
Element       = Expression | LiteralValue .

The LiteralType’s core type T must be a struct, array, slice, or map type (the syntax enforces this constraint except when the type is given as a TypeName).

So here we have the technical definition of a composite literal, and the more human readable explanation: A composite literal in Go is an expression that evaluates to a composite value. A composite value, in turn, is a type with a core type of struct, array, slice, or map.

There’s one caveat here, mentioned in parenthesis. When we’re using a composite type directly, the syntax itself enforces compliance with this rule.

var x = map[string]string{"a": "b"}

The ambiguity arises when using named types:

type Foo map[string]string
type Bar int

var x = Foo{"a": "b"} // Completely valid
var y = Bar{"a": "b"} // Syntactically valid, but logically incorrect, because named type Bar does not have a composite core type.

Quotes from The Go Programming Language Specification Version of August 2, 2023

Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content

Composite keys

This week’s episode of the Cup o’ Go podcast is out! Keep up with the Go community in just 15 minutes per week! Have a listen! Composite literals … The key is interpreted as a field name for struct literals, an index for array and slice literals, and a key for map literals. For map literals, all elements must have a key. If you’ve written any Go code, you probably already know about keys in maps:

Assignability of composite components

Composite literals … The types of the elements and keys must be [assignable(] to the respective field, element, and key types of type T; there is no additional conversion. This shouldn’t be surprising, but let’s examine the implications just the same. type myStr string s := myStr("my string") var x = map[int]string{ 3: "oink", // Valid, untyped numeric constant 3 is assignable to an int. int(4): "quack", // Valid, int(4) is of type int int64(12): "moo", // Invalid, int64(12) is not converted to int 8: s, // Invalid, type myStr is type string 9: string(s), // Valid; explicit conversion to type string } Quotes from The Go Programming Language Specification Version of August 2, 2023

Array and slice literals

Composite literals … For array and slice literals the following rules apply: Each element has an associated integer index marking its position in the array. An element with a key uses the key as its index. The key must be a non-negative constant representable by a value of type int; and if it is typed it must be of integer type. An element without a key uses the previous element’s index plus one.