(Tenía la sensación de que las respuestas anteriores todavía no indicaban las diferencias y las relaciones entre ellas string
y []rune
muy claramente, por lo que trataría de agregar otra respuesta con un ejemplo).
Como @Strangework
decía la respuesta, string
y []rune
son silenciosamente diferentes.
Diferencias - string
& []rune
:
string value
es un segmento de byte de solo lectura. Y, un literal de cadena está codificado en utf-8. Cada char en string
realidad toma 1 ~ 3 bytes, mientras que cada rune
toma 4 bytes
- Para
string
, ambos len()
y el índice se basan en bytes.
- Para
[]rune
, ambos len()
y el índice se basan en runas (o int32).
Relaciones - string
y []rune
:
- Cuando convierte de
string
a []rune
, cada carácter utf-8 en esa cadena se convierte en a rune
.
- Del mismo modo, en la conversión inversa, cuando se convierte de
[]rune
a string
, cada uno se rune
convierte en un carácter utf-8 en el string
.
Consejos:
- Puede convertir entre
string
y []rune
, pero aún así son diferentes, tanto en tipo como en tamaño general.
(Añadiría un ejemplo para mostrarlo más claramente).
Código
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()
}
Ejecutar:
ir a ejecutar string_rune_compare.go
Salida:
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
Explicación:
La cadena hello你好
tiene una longitud de 11, porque los primeros 5 caracteres toman cada uno solo 1 byte, mientras que los últimos 2 caracteres chinos toman 3 bytes cada uno.
- Así,
total bytes = 5 * 1 + 2 * 3 = 11
- Como la
len()
cadena se basa en bytes, la primera línea impresalen: 11
- Dado que el índice en la cadena también se basa en bytes, las siguientes 2 líneas imprimen valores de tipo
uint8
(ya que byte
es un tipo de alias uint8
, in go).
Al convertir el string
a []rune
, encontró 7 caracteres utf8, por lo tanto, 7 runas.
- Dado que
len()
en []rune
se basa en la runa, por lo tanto, la última línea impresa len: 7
.
- Si opera a
[]rune
través del índice, accederá a la base en runas.
Dado que cada runa es de un carácter utf8 en la cadena original, también puede decir que tanto la len()
operación de índice como la []rune
basada se basan en caracteres utf8.