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.
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.
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.
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
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
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.
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.
(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 rune
4 Bytes benötigtstring
basieren sowohl len()
als auch der Index auf Bytes.[]rune
basieren len()
und index auf rune (oder int32).Beziehungen - string
& []rune
:
string
in []rune
konvertieren, wird jedes utf-8-Zeichen in dieser Zeichenfolge zu rune
.[]rune
in string
jede rune
zu einem utf-8-Zeichen in der string
.Tipps:
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.)
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.
total bytes = 5 * 1 + 2 * 3 = 11
len()
on string auf Bytes basiert, wird die erste Zeile len: 11
gedruckt.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.
len()
auf []rune
auf Rune basiert, wird die zuletzt gedruckte Zeile len: 7
ausgegeben.[]rune
über den Index betreiben, wird auf die Basis der Rune zugegriffen.len()
als auch die Indexoperation für []rune
auf utf8-Zeichen basieren.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.