Как я могу перебирать строку с помощью рун в Go?

Я хотел:

for i := 0; i < len(str); i++ {
    dosomethingwithrune(str[i]) // takes a rune
}

Но оказывается, что str[i] имеет тип byte (uint8), а не rune.

Как я могу перебирать строку с помощью рун, а не байтов?

Ответ 1

См. этот пример из Эффективный переход:

for pos, char := range "日本語" {
    fmt.Printf("character %c starts at byte position %d\n", char, pos)
}

Отпечатки:

character 日 starts at byte position 0
character 本 starts at byte position 3
character 語 starts at byte position 6

Для строк диапазон больше работает для вас, вызывая индивидуальные Unicode кодовые точки, анализируя UTF-8.

Ответ 2

Например:

package main

import "fmt"

func main() {
        for i, rune := range "Hello, 世界" {
                fmt.Printf("%d: %c\n", i, rune)
        }
}

Игровая площадка


Вывод:

0: H
1: e
2: l
3: l
4: o
5: ,
6:  
7: 世
10: 界

Ответ 3

Чтобы отразить пример, приведенный в golang.org, Go позволяет легко преобразовать строку в кусок рун, а затем перебрать что, как и вы хотели изначально:

runes := []rune("Hello, 世界")
for i := 0; i < len(runes) ; i++ {
    fmt.Printf("Rune %v is '%c'\n", i, runes[i])
}

Конечно, мы могли бы также использовать оператор диапазона, как и в других примерах здесь, но это более внимательно следует вашему оригинальному синтаксису. В любом случае это будет выводить:

Rune 0 is 'H'
Rune 1 is 'e'
Rune 2 is 'l'
Rune 3 is 'l'
Rune 4 is 'o'
Rune 5 is ','
Rune 6 is ' '
Rune 7 is '世'
Rune 8 is '界'

Обратите внимание, что поскольку тип rune является псевдонимом для int32, мы должны использовать %c вместо обычного %v в инструкции Printf, или мы увидим целочисленное представление кода Unicode (см. Tour of Go).