10

In a pub quiz by Dave Cheney I came across the following construct:

a := [...]int{5, 4: 1, 0, 2: 3, 2, 1: 4}
fmt.Println(a)

>> [5 4 3 2 1 0]

(Playground Link)

It seems you can use keys in the initialization fields of an array (4: 1, 0 means set element at index 4 to 1, element at index 5 to 0). I have never seen something like this before. What is its use case? Why not set the particular index directly?

icza
  • 389,944
  • 63
  • 907
  • 827
RickyA
  • 15,465
  • 5
  • 71
  • 95
  • Ok, so spare arrays. Has anybody used/seen this in the wild? Seems like a good thing on paper, but not in practice (except for pub quizzes of course). – RickyA Mar 30 '16 at 08:19
  • since when is this syntax? never heard of this before XD – Kokizzu Oct 06 '21 at 06:06

3 Answers3

14

In composite literals the key (index in case of array and slice literals) can be optionally provided.

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 constant integer expression.
  • An element without a key uses the previous element's index plus one. If the first element has no key, its index is zero.

Elements get the zero value of the element type whose value is not specified.

You can use this to:

  • more compactly initialize arrays and slices if the array/slice has many zero values and just a few non-zero values

  • skip ("jump over") contiguous parts when enumerating elements, and the skipped elements will be initialized with the zero values

  • specify the first couple of elements, and still specify the length (max index + 1) you want the array/slice to have:

      a := []int{10, 20, 30, 99:0} // Specify first 3 elements and set length to 100
    

The spec also contains an example: create an array which tells if a character is a vowel. This is a very compact and talkative way to initialize the array:

// vowels[ch] is true if ch is a vowel
vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}

Another example: let's create a slice which tells if a day is weekend; Monday being 0, Tuesday being 1, ... and Sunday being 6:

weekend := []bool{5: true, 6: true} // The rest will be false

Or even better, you can even omit the 2nd index (6) as it will be implicitly 6 (previous +1):

weekend := []bool{5: true, true} // The rest will be false
Community
  • 1
  • 1
icza
  • 389,944
  • 63
  • 907
  • 827
2

If your array indices are sparse, it's shorter than doing {1,0,0,0,0,2,0,0,0,0,3} etc, and it's shorter than multiple assignment lines, so I'm guessing that's the use case.

I've never seen this syntax used before anywhere.

Not_a_Golfer
  • 47,012
  • 14
  • 126
  • 92
  • You were first, but I will accept icza's answer since it is more comprehensive. You have my upvote though. – RickyA Mar 30 '16 at 08:18
  • @RickyA it's cool, icza's answers are always comprehensive and educational, and indeed he gave a much better answer. – Not_a_Golfer Mar 30 '16 at 09:02
0

This can be useful when declaring and initializing arrays at the same time, especially globals that would otherwise need an init function to do something like this (Saturday and Sunday default to false)

var businessDays = [7]bool{
  time.Monday: true,
  time.Tuesday: true,
  time.Wednesday: true,
  time.Thursday: true,
  time.Friday: true,
}
geg
  • 4,399
  • 4
  • 34
  • 35