Qu'est-ce qu'une rune
dans Go?
Je suis allé sur Google mais Golang ne dit que sur une ligne: rune
EST UN ALIAS POUR int32
.
Mais comment se fait-il que des entiers soient utilisés partout comme pour échanger des cas?
Ce qui suit est un swapcase de fonction . Qu'est-ce que tous les <=
et -
?
Et pourquoi switch
n'a-t-il aucun argument?
&&
devrait signifier et mais qu'est-ce que r <= 'z'
?
func SwapRune(r rune) rune {
switch {
case 'a' <= r && r <= 'z':
return r - 'a' + 'A'
case 'A' <= r && r <= 'Z':
return r - 'A' + 'a'
default:
return r
}
}
La plupart d'entre eux proviennent de http://play.golang.org/p/H6wjLZj6lW
func SwapCase(str string) string {
return strings.Map(SwapRune, str)
}
Je comprends que cela mappe rune
à string
afin qu’il puisse renvoyer la chaîne échangée. Mais je ne comprends pas comment fonctionne exactement rune
ou byte
ici.
Les littéraux Rune ne sont que des valeurs entières de 32 bits (cependant, ce sont des constantes non typées, leur type peut donc changer}). Ils représentent des points de code unicode. Par exemple, le littéral runique 'a'
est en fait le nombre 97
.
Par conséquent, votre programme est à peu près équivalent à:
package main
import "fmt"
func SwapRune(r rune) rune {
switch {
case 97 <= r && r <= 122:
return r - 32
case 65 <= r && r <= 90:
return r + 32
default:
return r
}
}
func main() {
fmt.Println(SwapRune('a'))
}
Cela devrait être évident si vous examiniez le mappage Unicode, qui est identique à ASCII dans cette plage. De plus, 32 est en fait le décalage entre les points de code majuscules et minuscules du caractère. Donc, en ajoutant 32
à 'A'
, vous obtenez 'a'
et vice versa.
Notes de publication de Go lang: http://golang.org/doc/go1#rune
La rune est un type. Il occupe 32 bits et est censé représenter un UnicodeCodePoint . Par analogie, le jeu de caractères anglais codé en 'ASCII' contient 128 points de code. Ainsi, est capable de tenir dans un octet (8 bits). À partir de cette hypothèse (erronée), C a traité les caractères comme des "octets" char
et des "chaînes" comme une "séquence de caractères" char*
.
Mais devinez quoi. Il existe de nombreux autres symboles inventés par les humains autres que les symboles "abcde ..". Et il y en a tellement qu'il nous faut 32 bits pour les encoder.
Dans golang, string
est une suite de bytes
. Cependant, comme plusieurs octets peuvent représenter un point de code de rune, une valeur de chaîne peut également contenir des runes. Donc, il peut être converti en un []rune
, ou vice versa.
Le package unicode http://golang.org/pkg/unicode/ peut donner un aperçu de la richesse du défi.
Je n'ai pas assez de réputation pour poster un commentaire dans la réponse de fabrizioM, je devrai donc le poster ici.
La réponse de Fabrizio est en grande partie correcte et il a certainement capturé l'essence du problème - bien qu'il y ait une distinction à faire.
Une chaîne est PAS nécessairement une séquence de runes. C'est un wrapper sur une "tranche d'octets", une tranche étant un wrapper sur un tableau Go. Quelle différence cela fait-il?
Un type de runes est nécessairement une valeur de 32 bits, ce qui signifie qu'une séquence de valeurs de types de runes doit nécessairement comporter un certain nombre de bits x * 32. Les chaînes, étant une séquence d'octets, ont plutôt une longueur de x * 8 bits. Si toutes les chaînes étaient réellement en Unicode, cette différence n'aurait aucun impact. Comme les chaînes sont des tranches d'octets, Go peut utiliser ASCII ou tout autre codage d'octets arbitraire.
Les littéraux de chaîne, cependant, doivent être écrits dans la source encodée en UTF-8.
Source d'information: http://blog.golang.org/strings
J'ai essayé de garder mon langage simple afin qu'un profane comprenne rune
.
Une rune est un personnage. C'est tout.
C'est un personnage unique. C'est un personnage de n'importe quel alphabet de n'importe quelle langue du monde.
Pour obtenir une chaîne, nous utilisons
double-quotes ""
OR
back-ticks ``
Une chaîne est différente d'une rune. Dans les runes, nous utilisons
single-quotes ''
Maintenant, une rune est aussi un alias pour int32
... Uh Quoi?
La raison pour laquelle rune est un alias pour int32
, c’est parce que nous voyons cela avec des schémas de codage tels que ceux décrits ci-dessous
chaque personnage correspond à un certain nombre et il s’agit donc du nombre que nous stockons. Par exemple, a est mappé sur 97 et lorsque nous stockons ce numéro, il ne s'agit que de ce numéro. C'est ainsi que rune est un alias d'Int32. Mais ce n'est pas n'importe quel nombre. C'est un nombre avec 32 "zéros et des" ou "4" octets. (Remarque: UTF-8 est un schéma de codage à 4 octets)
Quel est le lien entre les runes et les chaînes?
Une chaîne est une collection de runes. Dans le code suivant:
package main
import (
"fmt"
)
func main() {
fmt.Println([]byte("Hello"))
}
Nous essayons de convertir une chaîne en un flux d'octets. La sortie est:
[72 101 108 108 111]
Nous pouvons voir que chacun des octets constituant cette chaîne est une rune.
Tout le monde a couvert la partie relative aux runes, donc je ne vais pas en parler.
Cependant, il y a aussi une question liée à switch
n'ayant aucun argument. Ceci est simplement dû au fait que, dans Golang, switch
sans expression est une autre façon d’exprimer la logique if/else. Par exemple, écrivez ceci:
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
est identique à écrire ceci:
t := time.Now()
if t.Hour() < 12 {
fmt.Println("It's before noon")
} else {
fmt.Println("It's after noon")
}
Vous pouvez en lire plus ici .
(J'ai l'impression que les réponses ci-dessus ne précisent toujours pas très clairement les différences et les relations entre string
et []rune
, aussi j'essaierais d'ajouter une autre réponse.}
Comme le dit la réponse de @Strangework
, string
et []rune
sont très différents.
Différences - string
& []rune
:
string value
est une tranche d'octet en lecture seule. Et un littéral de chaîne est codé en utf-8. Chaque caractère dans string
prend réellement 1 ~ 3 octets, tandis que chaque rune
prend 4 octetsstring
, len()
et index sont tous deux basés sur des octets.[]rune
, len()
et index sont tous deux basés sur rune (ou int32). Relations - string
& []rune
:
string
en []rune
, chaque caractère utf-8 de cette chaîne devient un rune
.[]rune
en string
, chaque rune
devient un caractère utf-8 dans string
.Conseils:
string
et []rune
, mais ils sont néanmoins différents, à la fois en type et en taille.(J'ajouterais un exemple pour le montrer plus clairement.)} _
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()
}
Exécuter:
allez lancer string_rune_compare.go
Sortie:
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
Explication:
La chaîne hello你好
a une longueur de 11, car les 5 premiers caractères prennent chacun 1 octet seulement, alors que les 2 derniers caractères chinois prennent chacun 3 octets.
total bytes = 5 * 1 + 2 * 3 = 11
len()
sur la chaîne est basé sur des octets, la première ligne imprimée len: 11
uint8
(puisque byte
est un type d'alias de uint8
, in go).Lors de la conversion de string
en []rune
, il a trouvé 7 caractères utf8, soit 7 runes.
len()
sur []rune
est basé sur rune, la dernière ligne imprimée est donc len: 7
.[]rune
via index, il accédera à la base sur rune.len()
et l’opération d’indexation sur []rune
sont basés sur les caractères utf8.Une rune est une valeur int32 et, par conséquent, un type Go utilisé pour représenter un point de code Unicode. Un point de code Unicode ou une position de code est une valeur numérique généralement utilisée pour représenter des caractères Unicode uniques.