web-dev-qa-db-de.com

Was ist eine Rune?

Was ist eine rune in Go?

Ich habe gegoogelt, aber Golang sagt nur in einer Zeile: rune IST EIN ALIAS ​​FÜR int32.

Aber wie kommt es, dass ganze Zahlen verwendet werden, wie beim Tauschen von Fällen?

Das Folgende ist eine Funktion swapcase . Was ist der <= und -?

Und warum hat switch keine Argumente? 

&& sollte und bedeuten, aber was ist 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
    }
}

Die meisten von ihnen stammen aus http://play.golang.org/p/H6wjLZj6lW

func SwapCase(str string) string {
    return strings.Map(SwapRune, str)
}

Ich verstehe, dass dies rune zu string abbildet, so dass der ausgelagerte String zurückgegeben werden kann. Aber ich verstehe nicht, wie genau rune oder byte hier funktioniert.

125
user2671513

Runenliterale sind nur 32-Bit-Integer-Werte (jedoch sind sie nicht typisierte Konstanten, daher kann sich ihr Typ ändern). Sie repräsentieren Unicode-Codepunkte. Beispielsweise ist das Runenliteral 'a' tatsächlich die Nummer 97.

Daher ist Ihr Programm ziemlich gleichbedeutend mit:

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'))
}

Es sollte offensichtlich sein, wenn Sie sich die Unicode-Zuordnung ansehen, die mit ASCII in diesem Bereich identisch ist. Außerdem ist 32 tatsächlich der Versatz zwischen dem Groß- und Kleinbuchstaben des Zeichens. Indem Sie 32 zu 'A' hinzufügen, erhalten Sie 'a' und umgekehrt.

104
topskip

Aus den Versionshinweisen zu Go lang: http://golang.org/doc/go1#rune

Rune ist ein Typ. Es belegt 32 Bit und soll einen UnicodeCodePoint ..__ darstellen. Analog dazu enthält der in 'ASCII' codierte englische Zeichensatz 128 Codepunkte. Somit ist es möglich, in ein Byte (8bit) zu passen. Aus dieser (fehlerhaften) Annahme heraus behandelte C Zeichen als 'Bytes' char und 'Strings' als 'Zeichenfolge' char*.

Aber rate mal was. Es gibt viele andere Symbole, die von Menschen erfunden wurden, außer den Symbolen "abcde ..". Und es gibt so viele, dass wir 32 Bit benötigen, um sie zu kodieren. 

In golang ist dann eine string eine Folge von bytes. Da jedoch mehrere Bytes einen Runen-Codepunkt darstellen können, kann ein Zeichenfolgenwert auch Runen enthalten. Es kann also in einen []rune konvertiert werden oder umgekehrt.

Das Unicode-Paket http://golang.org/pkg/unicode/ kann einen Einblick in den Reichtum der Herausforderung geben.

36
fabrizioM

Ich habe nicht genug Ruf, um einen Kommentar zu fabrizioMs Antwort zu posten, deshalb muss ich ihn hier posten.

Fabrizios Antwort ist weitgehend korrekt, und er hat sicherlich das Wesentliche des Problems eingefangen - obwohl es eine Unterscheidung gibt, die gemacht werden muss.

Ein String ist UND NICHT, notwendigerweise eine Folge von Runen. Hierbei handelt es sich um einen Wrapper über einem 'Byte-Byte', wobei ein Slice ein Wrapper über einem Go-Array ist. Welchen Unterschied macht das?

Ein Runentyp ist notwendigerweise ein 32-Bit-Wert, dh, eine Folge von Werten von Runentypen hätte notwendigerweise eine bestimmte Anzahl von Bits x * 32. Zeichenfolgen, die eine Folge von Bytes sind, haben stattdessen eine Länge von x * 8 Bits. Wenn alle Zeichenfolgen tatsächlich in Unicode sind, hätte dieser Unterschied keine Auswirkungen. Da Strings jedoch Byte-Abschnitte sind, kann Go ASCII oder eine beliebige andere Byte-Kodierung verwenden.

String-Literale müssen jedoch in die in UTF-8 codierte Quelle geschrieben werden.

Informationsquelle: http://blog.golang.org/strings

21
Strangework

Ich habe versucht, meine Sprache einfach zu halten, damit ein Laie rune versteht.

Eine Rune ist ein Charakter. Das war's.

Es ist ein einzelnes Zeichen. Es ist eine Figur aus einem beliebigen Alphabet aus einer beliebigen Sprache von überall auf der Welt.

Um eine Zeichenfolge zu erhalten, verwenden wir

double-quotes ""

OR

back-ticks ``

Eine Zeichenfolge unterscheidet sich von einer Rune. In Runen verwenden wir

single-quotes ''

Nun ist eine Rune auch ein Alias ​​für int32... Äh was?

Die Grundrune ist ein Alias ​​für int32 ist, weil wir sehen, dass mit Codierungsschemata wie unten enter image description here

jedes Zeichen ist einer Nummer zugeordnet und daher ist es die Nummer, die wir speichern. Zum Beispiel entspricht a 97 und wenn wir diese Zahl speichern, ist es nur die Zahl, und so ist rune ein Alias ​​für int32. Ist aber nicht irgendeine Zahl. Es ist eine Zahl mit 32 'Nullen und Einsen' oder '4' Bytes. (Hinweis: UTF-8 ist ein 4-Byte-Codierungsschema.)

In welcher Beziehung stehen Runen zu Strings?

Ein String ist eine Sammlung von Runen. Im folgenden Code:

    package main

    import (
        "fmt"
    )

    func main() {
        fmt.Println([]byte("Hello"))
    }

Wir versuchen, einen String in einen Bytestrom umzuwandeln. Die Ausgabe ist:

[72 101 108 108 111]

Wir können sehen, dass jedes der Bytes, aus denen diese Zeichenfolge besteht, eine Rune ist.

18
Suhail Gupta

Alle anderen haben sich mit Runen beschäftigt, daher werde ich nicht darüber sprechen.

Es gibt jedoch auch eine Frage, dass switch keine Argumente hat. Dies ist einfach so, weil switch in Golang eine alternative Möglichkeit ist, if/else-Logik auszudrücken. Zum Beispiel schreiben Sie dies:

t := time.Now()
switch {
case t.Hour() < 12:
    fmt.Println("It's before noon")
default:
    fmt.Println("It's after noon")
}

ist das gleiche wie das Schreiben:

t := time.Now()
if t.Hour() < 12 {
    fmt.Println("It's before noon")
} else {
    fmt.Println("It's after noon")
}

Sie können mehr hier lesen.

6
Shashank Goyal

(Ich habe das Gefühl, dass die obigen Antworten die Unterschiede und Beziehungen zwischen string und []rune noch nicht sehr klar angeben, also würde ich versuchen, eine weitere Antwort mit Beispiel hinzuzufügen.)

Wie die Antwort von @Strangework sagte, sind string und []rune ziemlich unterschiedlich.

Unterschiede - string & []rune:

  • string value ist ein schreibgeschütztes Byte-Segment. Ein Zeichenfolgenliteral wird in utf-8 codiert. Jedes Zeichen in string benötigt tatsächlich 1 ~ 3 Bytes, während jede rune4 Bytes benötigt
  • Bei string basieren sowohl len() als auch der Index auf Bytes.
  • Bei []rune basieren len() und index auf rune (oder int32).

Beziehungen - string & []rune:

  • Wenn Sie von string in []rune konvertieren, wird jedes utf-8-Zeichen in dieser Zeichenfolge zu rune.
  • Auf ähnliche Weise wird bei der umgekehrten Konvertierung bei der Konvertierung von []rune in string jede rune zu einem utf-8-Zeichen in der string.

Tipps:

  • Sie können zwischen string und []rune konvertieren, sie unterscheiden sich jedoch in Typ und Gesamtgröße.

(Ich würde ein Beispiel hinzufügen, um dies deutlicher zu zeigen.)


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()
}

Ausführen:

starten Sie string_rune_compare.go

Ausgabe:

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

Erläuterung:

  • Die Zeichenfolge hello你好 hat die Länge 11, da die ersten 5 Zeichen jeweils nur 1 Byte benötigen, während die letzten 2 chinesischen Zeichen jeweils 3 Byte benötigen.

    • Somit total bytes = 5 * 1 + 2 * 3 = 11
    • Da len() on string auf Bytes basiert, wird die erste Zeile len: 11 gedruckt.
    • Da index on string auch auf Bytes basiert, werden in den folgenden zwei Zeilen Werte des Typs uint8 ausgegeben (da byte ein Alias-Typ von uint8 ist, in go).
  • Beim Konvertieren der string in []rune wurden 7 utf8-Zeichen, also 7 Runen gefunden.

    • Da len() auf []rune auf Rune basiert, wird die zuletzt gedruckte Zeile len: 7 ausgegeben.
    • Wenn Sie []rune über den Index betreiben, wird auf die Basis der Rune zugegriffen.
      Da jede Rune von einem utf8-Zeichen in der ursprünglichen Zeichenfolge stammt, können Sie auch sagen, dass sowohl len() als auch die Indexoperation für []rune auf utf8-Zeichen basieren.
4
Eric Wang

Eine Rune ist ein int32-Wert und daher ein Go-Typ, der zur Darstellung eines Unicode-Codepunkts verwendet wird. Ein Unicode-Codepunkt oder eine Codeposition ist ein numerischer Wert, der normalerweise zur Darstellung einzelner Unicode-Zeichen verwendet wird. 

0
Remario