332 votes

Qu'est-ce qu'une rune?

Qu'est-ce qu'une rune en Go?

J'ai cherché sur Google mais Golang dit seulement en une ligne: rune est un alias pour int32.

Mais comment se fait-il que des entiers soient utilisés partout comme dans le cas du changement de cas?

Voici une fonction swapcase. Qu'est-ce que tous les <= et -?

Et pourquoi le switch n'a-t-il pas d'arguments?

&& devrait signifier et mais que signifie 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 pour qu'il puisse retourner la chaîne échangée. Mais je ne comprends pas exactement comment rune ou byte fonctionnent ici.

239voto

topskip Points 2665

Les littéraux de rune ne sont que des valeurs entières sur 32 bits (cependant ce sont des constantes non typées, donc leur type peut changer). Ils représentent des points de code Unicode. Par exemple, le littéral de rune 'a' est en réalité le nombre 97.

Par conséquent, votre programme est pratiquement é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'))
}

Il est évident, si vous deviez consulter la correspondance Unicode, qui est identique à ASCII dans cette plage. De plus, 32 est en fait le décalage entre le point de code en majuscules et en minuscules du caractère. Ainsi, en ajoutant 32 à 'A', vous obtenez 'a' et vice versa.

96voto

fabrizioM Points 11498

À partir des notes de publication de Go lang : http://golang.org/doc/go1#rune

Rune est un Type. Il occupe 32 bits et est destiné à représenter un CodePoint Unicode. Par analogie, l'ensemble des caractères anglais encodé dans 'ASCII' a 128 points de code. Ainsi, il peut s'adapter à l'intérieur d'un octet (8 bits). À partir de cette hypothèse (erronée), C traitait les caractères comme des 'bytes' char, et les 'chaînes de caractères' comme une 'séquence de caractères' char*.

Mais devinez quoi. Il y a beaucoup d'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.

Ensuite, en golang, une string est une séquence de bytes. Cependant, étant donné que plusieurs bytes peuvent représenter un point de code Rune, une valeur de chaîne peut aussi contenir des runes. Ainsi, elle peut être convertie 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.

68voto

Suhail Gupta Points 6071

J'ai essayé de garder mon langage simple pour qu'un profane comprenne rune.

Une rune est un caractère. C'est tout.

C'est un seul caractère. 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, nous utilisons

des guillemets doubles ""

OU

des backticks ``

Une chaîne est différente d'une rune. Dans les runes, nous utilisons

des apostrophes ''

Maintenant, une rune est également un alias pour int32...Uh Quoi?

La raison pour laquelle rune est un alias pour int32 est que nous voyons cela avec des schémas de codage tels que ci-dessous saisissez ici la description de l'image

chaque caractère est associé à un nombre et c'est donc le nombre que nous stockons. Par exemple, a est associé à 97 et lorsque nous stockons ce nombre, ce n'est que le nombre et c'est pourquoi rune est un alias pour int32. Mais ce n'est pas juste un 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 chaînes de caractères?

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 de caractères 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.

42voto

fly bird Points 818

(J'ai le sentiment que les réponses ci-dessus n'ont pas encore clairement indiqué les différences et les relations entre chaîne et []rune, donc j'essaierais d'ajouter une autre réponse avec un exemple.)

Comme l'a dit la réponse de @Strangework, chaîne et []rune sont assez différents.

Differences - chaîne & []rune:

  • la valeur de la chaîne est une tranche de bytes en lecture seule. Et, une littérale de chaîne est encodée en utf-8. Chaque caractère dans chaîne prend en réalité 1 ~ 3 bytes, tandis que chaque rune en prend 4
  • Pour chaîne, à la fois len() et l'index sont basés sur des bytes.
  • Pour []rune, à la fois len() et l'index sont basés sur des runes (ou int32).

Relations - chaîne & []rune:

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

Conseils:

  • Vous pouvez convertir entre chaîne et []rune, mais ils restent différents, à la fois en type et en taille globale.

(Je ajouterais un exemple pour montrer cela de manière plus claire.)


Code

string_rune_compare.go:

// comparaison de chaîne et rune,
package main

import "fmt"

// comparaison de chaîne et rune,
func stringAndRuneCompare() {
    // chaîne,
    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 // dernier 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écution:

go run 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 ne prennent chacun qu'un seul byte, tandis que les 2 derniers caractères chinois en prennent chacun 3.

    • Ainsi, total bytes = 5 * 1 + 2 * 3 = 11
    • Puisque len() sur une chaîne est basé sur des bytes, la première ligne affiche donc len: 11
    • Puisque l'index sur une chaîne est également basé sur des bytes, les 2 lignes suivantes affichent des valeurs de type uint8 (car byte est un type alias de uint8, en go).
  • Lors de la conversion de la chaîne en []rune, il a trouvé 7 caractères utf8, donc 7 runes.

    • Puisque len() sur []rune est basé sur des runes, la dernière ligne affiche donc len: 7.
    • Si vous manipulez []rune via un index, cela se fera en se basant sur les runes.
      Puisque chaque rune provient d'un caractère utf8 dans la chaîne d'origine, vous pouvez également dire que à la fois len() et les opérations d'index sur []rune sont basées sur les caractères utf8.

38voto

Strangework Points 545

Je n'ai pas assez de réputation pour poster un commentaire à la réponse de fabrizioM sur stackoverflow, donc je vais devoir le poster ici à la place.

La réponse de Fabrizio est en grande partie correcte, et il a certainement capturé l'essence du problème - bien qu'il soit nécessaire de faire une distinction.

Une chaîne de caractères n'est PAS nécessairement une séquence de runes. C'est un wrapper sur une 'slice de bytes', une slice étant un wrapper sur un array Go. Quelle est la différence?

Un type rune est nécessairement une valeur de 32 bits, ce qui signifie qu'une séquence de valeurs de types rune aurait nécessairement un certain nombre de bits x*32. Les chaînes de caractères, étant une séquence de bytes, ont plutôt une longueur de x*8 bits. Si toutes les chaînes de caractères étaient réellement en Unicode, cette différence n'aurait aucun impact. Puisque les chaînes de caractères sont des slices de bytes, cependant, Go peut utiliser ASCII ou tout autre encodage de bytes arbitraire.

Les littéraux de chaînes de caractères, cependant, doivent être écrits dans la source encodée en UTF-8.

Source d'information: http://blog.golang.org/strings

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X