Qu'est-ce qu'un rune
in Go?
J'ai cherché sur Google mais Golang ne dit qu'en une seule ligne: rune
est un alias pourint32
.
Mais comment se fait-il que les entiers soient utilisés partout comme des cas d'échange?
Ce qui suit est un cas d'échange de fonctions. Qu'est-ce que tout le <=
et -
?
Et pourquoi n'a pas switch
d'arguments?
&&
devrait signifier et mais qu'est-ce que c'est 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 qu'il s'agit d'un mappage rune
vers string
afin qu'il puisse renvoyer la chaîne permutée. Mais je ne comprends pas comment exactement rune
ou byte
fonctionne ici.
[]rune
peut être défini sur un type booléen, numérique ou chaîne. Voir stackoverflow.com/a/62739051/12817546 .Réponses:
Les littéraux runiques ne sont que des valeurs entières 32 bits ( mais 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 nombre97
.Par conséquent, votre programme équivaut à peu près à:
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 regardez 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.la source
unicode.ToLower(r rune) rune
.func SwapRune(r rune) rune { if unicode.IsUpper(r) { r = unicode.ToLower(r) } else { r = unicode.ToUpper(r) }; return r }
Extrait des notes de publication de Go lang: http://golang.org/doc/go1#rune
Rune est un type. Il occupe 32 bits et est censé représenter un Unicode CodePoint . Par analogie, le jeu de caractères anglais codés en «ASCII» a 128 points de code. Ainsi est capable de tenir à l'intérieur d'un octet (8 bits). A partir de cette hypothèse (erronée), C a traité les caractères comme des «octets»
char
et les «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 que nous avons besoin de 32 bits pour les encoder.
En golang, alors a
string
est une séquence debytes
. Cependant, comme plusieurs octets peuvent représenter un point de code runique, une valeur de chaîne peut également contenir des runes. Ainsi, il peut être converti en a[]rune
, ou vice versa.Le package unicode http://golang.org/pkg/unicode/ peut donner un avant-goût de la richesse du défi.
la source
rune
est similaireint32
et contient beaucoup de bits.string
est une séquence derune
s" - je ne pense pas que ce soit vrai? Aller au blog : "une chaîne n'est qu'un tas d'octets"; Go lang spec : "Une valeur de chaîne est une séquence (éventuellement vide) d'octets"not bytes
. Ensuite, vous pourriez dire: "Les chaînes sont constituées de runes et de runes d'octets" Quelque chose comme ça. Puis encore. ce n'est pas tout à fait vrai.J'ai essayé de garder mon langage simple pour qu'un profane le comprenne
rune
.Une rune est un personnage. C'est ça.
C'est un personnage unique. C'est un caractère de n'importe quel alphabet de n'importe quelle langue de n'importe où dans le monde.
Pour obtenir une chaîne que nous utilisons
double-quotes ""
OU
back-ticks ``
Une chaîne est différente d'une rune. Dans les runes que nous utilisons
single-quotes ''
Maintenant, une rune est aussi un alias pour
int32
... Euh Quoi?La raison pour laquelle rune est un alias pour
int32
est parce que nous voyons qu'avec des schémas de codage tels que ci-dessouschaque caractère correspond à un certain nombre et c'est donc le nombre que nous stockons. Par exemple, un correspond à 97 et lorsque nous stockons ce numéro, c'est juste le numéro et c'est ainsi que rune est un alias pour int32. Mais ce n'est pas n'importe quel nombre. C'est un nombre avec 32 «zéros et uns» ou «4» octets. (Remarque: UTF-8 est un schéma de codage sur 4 octets)
Comment les runes sont-elles liées aux cordes?
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 qui composent cette chaîne est une rune.
la source
A string is not a collection of runes
ce n'est pas exact à proprement parler. Au lieu de cela, string est une tranche d'octets, encodée avec utf8. Chaque caractère dans la chaîne prend en fait 1 à 3 octets, tandis que chaque rune prend 4 octets. Vous pouvez convertir entre une chaîne et une rune [], mais elles sont différentes.Je n'ai pas assez de réputation pour publier un commentaire sur la réponse de fabrizioM , je vais donc devoir le poster ici à la place.
La réponse de Fabrizio est en grande partie correcte et il a certainement saisi l'essence du problème - bien qu'il y ait une distinction à faire.
Une chaîne n'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 rune est nécessairement une valeur de 32 bits, ce qui signifie qu'une séquence de valeurs de types de runes aurait nécessairement un certain nombre de bits x * 32. Les chaînes, qui sont une séquence d'octets, ont à la place une longueur de x * 8 bits. Si toutes les chaînes étaient réellement en Unicode, cette différence n'aurait aucun impact. Cependant, comme les chaînes sont des tranches d'octets , Go peut utiliser ASCII ou tout autre codage d'octets arbitraire.
Cependant, les littéraux de chaîne doivent être écrits dans la source codée en UTF-8.
Source d'informations: http://blog.golang.org/strings
la source
(J'ai le sentiment que les réponses ci-dessus n'indiquent toujours pas les différences et les relations entre
string
et[]rune
très clairement, alors j'essaierais d'ajouter une autre réponse avec un exemple.)Comme
@Strangework
l'a dit la réponse,string
et[]rune
sont calmes différents.Différences -
string
&[]rune
:string value
est une tranche d'octets en lecture seule. Et, une chaîne littérale est codée en utf-8. Chaque caractèrestring
prend en fait 1 à 3 octets, tandis que chacunrune
prend 4 octetsstring
, les deuxlen()
et index sont basés sur des octets.[]rune
, les deuxlen()
et index sont basés sur rune (ou int32).Relations -
string
&[]rune
:string
en[]rune
, chaque caractère utf-8 de cette chaîne devient unrune
.[]rune
enstring
, chacunrune
devient un caractère utf-8 dans le fichierstring
.Conseils:
string
et[]rune
, mais ils sont toujours différents, à la fois dans le type et la taille globale.(J'ajouterais un exemple pour le montrer plus clairement.)
Code
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:
Production:
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, tandis que les 2 derniers caractères chinois prennent chacun 3 octets.total bytes = 5 * 1 + 2 * 3 = 11
len()
chaîne est basée sur des octets, la première ligne est donc impriméelen: 11
uint8
(puisquebyte
c'est un type d'alias deuint8
, in go).Lors de la conversion du
string
to[]rune
, il a trouvé 7 caractères utf8, donc 7 runes.len()
on[]rune
est basé sur la rune, donc la dernière ligne est impriméelen: 7
.[]rune
via index, il accédera à la base sur la rune.Étant donné que chaque rune provient d'un caractère utf8 dans la chaîne d'origine, vous pouvez donc également dire que les deux
len()
et les opérations d'indexation[]rune
sont basées sur les caractères utf8.la source
fmt.Println("hello你好"[0])
cela renvoie le point de code UTF-8 réel au lieu d'octets.s[0]
, il affiches[0]: 104, type: uint8
, le type estuint8
, signifie que c'est un octet. Pour les caractères ASCII commeh
utf-8, utilisez également un seul octet pour le représenter, de sorte que le point de code est le même que l'octet unique; mais pour les caractères chinois comme你
, il utilise 3 octets.Tout le monde a couvert la partie liée aux runes, donc je ne vais pas en parler.
Cependant, il y a aussi une question liée au fait de
switch
ne pas avoir d'arguments. C'est simplement parce que dans Golang,switch
sans expression est une autre façon d'exprimer la logique if / else. Par exemple, en écrivant ceci:t := time.Now() switch { case t.Hour() < 12: fmt.Println("It's before noon") default: fmt.Println("It's after noon") }
équivaut à é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 savoir plus ici .
la source
Une rune est une valeur int32 et, par conséquent, il s'agit d'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;
la source