Sobes.tech
Middle

What nuances should be considered when iterating over a string in Go?

sobes.tech AI

Answer from AI

When iterating over a string in Go using a for range loop, the following nuances are considered:

  • Unicode code points (runes): for range iterates over Unicode code points (runes), not bytes. This means each iteration element represents a single rune (rune, an alias for int32), not a separate byte.
  • Byte offset: Each iteration of for range returns two values: the byte offset (int) and the current rune (rune). The offset indicates the starting byte of the current rune in the string.
  • Multibyte characters: If the string contains multibyte Unicode characters (e.g., Cyrillic, emojis), for range handles them correctly, perceiving each character as a single rune, even if it occupies multiple bytes in the underlying []byte representation of the string.
  • Iteration over bytes: To iterate over individual bytes of the string, you can use a regular for loop with an index, accessing the string as a byte array: s[i]. In this case, each iteration element will be of type byte.
  • Performance: Iterating over runes with for range may be slightly slower than iterating over bytes with a regular for, especially for strings consisting only of ASCII characters (where 1 rune = 1 byte). However, for strings with multibyte characters, for range is a more correct and preferred way of iteration.

Example:

package main

import "fmt"

func main() {
	str := "Привет, Go!"

	// Iteration over runes (Unicode code points)
	fmt.Println("Iteration over runes:")
	for index, r := range str {
		fmt.Printf("Byte offset: %d, Rune: %c (type: %T)\n", index, r, r)
	}

	fmt.Println("\nIteration over bytes:")
	// Iteration over bytes
	for i := 0; i < len(str); i++ {
		fmt.Printf("Index: %d, Byte: %d (type: %T)\n", i, str[i], str[i])
	}
}