(У меня сложилось впечатление, что приведенные выше ответы по-прежнему не отражают различия и отношения между ними string
и []rune
очень четко, поэтому я постараюсь добавить еще один ответ с примером.)
Как @Strangework
сказал ответ, string
и []rune
тихо разные.
Отличия - string
& []rune
:
string value
является байтовым срезом только для чтения. И строковый литерал закодирован в utf-8. Каждый символ в string
действительности занимает 1 ~ 3 байта, в то время как каждый rune
занимает 4 байта
- Ибо
string
, len()
и индекс основаны на байтах.
- Ибо
[]rune
, len()
и индекс основаны на руне (или int32).
Отношения - string
& []rune
:
- Когда вы конвертируете из
string
в []rune
, каждый символ utf-8 в этой строке становится rune
.
- Точно так же при обратном преобразовании, при преобразовании из
[]rune
в string
, каждый rune
становится символом utf-8 в string
.
Подсказки:
- Вы можете конвертировать между
string
и []rune
, но все же они разные, как по типу, так и по общему размеру.
(Я хотел бы добавить пример, чтобы показать это более четко.)
Код
string_rune_compare.go:
// string & rune compare,
package main
import "fmt"
// string & rune compare,
func stringAndRuneCompare() {
// string,
s := "hello你好"
fmt.Printf("%s, type: %T, len: %d\n", s, s, len(s))
fmt.Printf("s[%d]: %v, type: %T\n", 0, s[0], s[0])
li := len(s) - 1 // last index,
fmt.Printf("s[%d]: %v, type: %T\n\n", li, s[li], s[li])
// []rune
rs := []rune(s)
fmt.Printf("%v, type: %T, len: %d\n", rs, rs, len(rs))
}
func main() {
stringAndRuneCompare()
}
Выполнение:
иди беги string_rune_compare.go
Вывод:
hello你好, type: string, len: 11
s[0]: 104, type: uint8
s[10]: 189, type: uint8
[104 101 108 108 111 20320 22909], type: []int32, len: 7
Объяснение:
Строка hello你好
имеет длину 11, потому что первые 5 символов занимают по 1 байту, а последние 2 символа по 3 байта.
- Таким образом,
total bytes = 5 * 1 + 2 * 3 = 11
- Поскольку
len()
строка основана на байтах, первая строка печатаетсяlen: 11
- Поскольку индекс по строке также основан на байтах, таким образом, следующие 2 строки выводят значения типа
uint8
(так byte
как это псевдоним типа uint8
в go).
Когда конвертировать string
в []rune
, он нашел 7 utf8 символов, таким образом 7 рун.
- Так как
len()
на []rune
основе руны, то последняя строка печатается len: 7
.
- Если вы работаете
[]rune
через индекс, он получит доступ к базе на руне.
Поскольку каждая руна взята из символа utf8 в исходной строке, вы также можете сказать, что len()
и операция с индексами []rune
основаны на символах utf8.