web-dev-qa-db-fra.com

Qu'est-ce qu'une rune?

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.

125
user2671513

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.

104
topskip

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.

36
fabrizioM

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

21
Strangework

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  enter image description here

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.

16
Suhail Gupta

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 .

6
Shashank Goyal

(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 octets
  • Pour string, len() et index sont tous deux basés sur des octets.
  • Pour []rune, len() et index sont tous deux basés sur rune (ou int32).

Relations - string & []rune:

  • Lorsque vous convertissez de string en []rune, chaque caractère utf-8 de cette chaîne devient un rune.
  • De même, dans la conversion inverse, lors de la conversion de []rune en string, chaque rune devient un caractère utf-8 dans string.

Conseils:

  • Vous pouvez convertir entre 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.)} _


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:

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.

    • Ainsi, total bytes = 5 * 1 + 2 * 3 = 11
    • Puisque len() sur la chaîne est basé sur des octets, la première ligne imprimée len: 11
    • Comme l'index sur chaîne est également basé sur des octets, les deux lignes suivantes impriment les valeurs de type 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.

    • Puisque len() sur []rune est basé sur rune, la dernière ligne imprimée est donc len: 7.
    • Si vous utilisez []rune via index, il accédera à la base sur rune.
      Comme chaque rune provient d’un caractère utf8 dans la chaîne d’origine, vous pouvez donc également dire que len() et l’opération d’indexation sur []rune sont basés sur les caractères utf8.
4
Eric Wang

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. 

0
Remario