Die beste Codierungsmethode in Go besteht darin, beim Konvertieren eines Strings in Bytes ein Byte- Slice []byteund kein festgelegtes Byte-Array [20]bytezu verwenden ... Glauben Sie mir nicht? Schauen Sie sich Rob Pikes Antwort auf diesen Thread an
openwonk
9
Das OP fragte nach einem Array, nicht nach einem Slice. In einigen Fällen müssen Sie die Größe des Slice begrenzen und stattdessen ein Array verwenden. Meine Antwort unten schneidet die zusätzlichen Zeichen ab, um sicherzustellen, dass Sie das Array nicht überlaufen.
DavidG
3
Für diejenigen, die denken, dass dies ein bisschen seltsam aussieht: Dies ist nur eine Typkonvertierung in Go: golang.org/ref/spec#Conversions
Cnly
Gibt es eine Möglichkeit, mehrere Zeichenfolgen hinzuzufügen und zu verketten? zB []byte("one", "two")?
Rakim
Leider nein, @rakim, Sie können nur eine Zeichenfolge übergeben. Sie müssen sie also zuerst verketten oder mehrere Byte-Slices kombinieren (außerhalb des Geltungsbereichs dieser Frage).
openwonk
149
Zum Konvertieren von einer Zeichenfolge in ein Byte-Slice string -> []byte:
[]byte(str)
Zum Konvertieren eines Arrays in ein Slice [20]byte -> []byte:
arr[:]
Zum Kopieren einer Zeichenfolge in ein Array string -> [20]byte:
copy(arr[:], str)
Wie oben, jedoch wird die Zeichenfolge zuerst explizit in ein Slice konvertiert:
copy(arr[:],[]byte(str))
Die Einbau- copyFunktion nur Kopien auf eine Scheibe, aus einem Stück.
Arrays sind "die zugrunde liegenden Daten", während Slices "ein Ansichtsfenster für zugrunde liegende Daten" sind.
Durch [:]die Verwendung wird ein Array als Slice qualifiziert.
Eine Zeichenfolge nicht als Scheibe zu qualifizieren , die kopiert werden können , um , aber es gilt als eine Scheibe , die kopiert werden können , aus (Strings sind unveränderlich).
Wenn die Zeichenfolge zu lang ist, copywird nur der Teil der Zeichenfolge kopiert, der passt.
Dieser Code:
var arr [20]byte
copy(arr[:],"abc")
fmt.Printf("array: %v (%T)\n", arr, arr)
Möglicherweise möchten Sie ein Beispiel für die Konvertierung eines einzelnen Zeichens hinzufügen. Daraus habe ich geschlossen, dass es b[i] = []byte("A")[0]funktioniert, aber b[i] = 'A'am Ende viel sauberer ist.
Alex Jansen
1
Das funktioniert nicht für Multi-Byte-Runen:b[1] = '本'
Alexander
110
Zum Beispiel,
package main
import"fmt"
func main(){
s :="abc"var a [20]byte
copy(a[:], s)
fmt.Println("s:",[]byte(s),"a:", a)}
Dies ist die einzige Antwort, die sich tatsächlich mit der ursprünglichen Frage befasst.
Jack O'Connor
Warum sollten Sie 20 Bytes zuweisen, anstatt genau zu bestimmen, was Sie tatsächlich für die Zeichenfolge benötigen? Wenn die Zeichenfolge weniger als 20 benötigt, ist das nicht ineffizient? Und auch fehleranfällig, wenn es 20 überschreitet?
Sir
1
@ Sir: Wir weisen keine 20 Bytes zu. Wir kopieren 3 Bytes, die Länge von s, Die Kopierfunktion ist nicht dumm. Anhängen an und Kopieren von Slices : "Die Anzahl der kopierten Elemente ist das Minimum von len (src) und len (dst)."
Dies scheint die Frage nicht zu beantworten. OP wollte die Bytes der Zeichenfolge in ein vorhandenes Array schreiben, das möglicherweise länger als die Zeichenfolge ist.
Jack O'Connor
2
Die Verwendung von Slices []bytewird Arrays vorgezogen [20]byte. Die Antwort ist korrekt, basierend auf Best Practices. Wenn Spezifikationen oder Code Arrays erfordern, verwenden Sie copystattdessen (siehe Beispiele an anderer Stelle in diesem Thread).
Es ist nicht besser. Es ist falsch. Es macht nicht das, wonach die Frage gestellt hat.
PeterSO
10
Konvertieren Sie eine Zeichenfolge in ein Byte-Slice
Sie benötigen eine schnelle Möglichkeit, eine [] Zeichenfolge in einen [] Bytetyp zu konvertieren. Zur Verwendung in Situationen wie dem Speichern von Textdaten in einer Direktzugriffsdatei oder einer anderen Art der Datenmanipulation, bei der die Eingabedaten vom Typ [] Byte sein müssen.
package main
func main(){var s string//...
b :=[]byte(s)//...}
Dies ist nützlich, wenn ioutil.WriteFile verwendet wird, das einen Byte-Slice als Datenparameter akzeptiert:
WriteFile func(filename string, data []byte, perm os.FileMode) error
Ein anderes Beispiel
package main
import("fmt""strings")
func main(){
stringSlice :=[]string{"hello","world"}
stringByte := strings.Join(stringSlice," ")// Byte array value
fmt.Println([]byte(stringByte))// Corresponding string value
fmt.Println(string([]byte(stringByte)))}
Am Ende wurden Array-spezifische Methoden erstellt, um dies zu tun. Ähnlich wie das Codierungs- / Binärpaket mit spezifischen Methoden für jeden int-Typ. Zum Beispiel binary.BigEndian.PutUint16([]byte, uint16).
func byte16PutString(s string)[16]byte{var a [16]byteif len(s)>16{
copy(a[:], s)}else{
copy(a[16-len(s):], s)}return a
}var b [16]byte
b = byte16PutString("abc")
fmt.Printf("%v\n", b)
Ausgabe:
[0000000000000979899]
Beachten Sie, wie ich links und nicht rechts auffüllen wollte.
Wenn Sie die Antwort ablehnen, hinterlassen Sie bitte einen Kommentar dazu, warum Sie die Lösung nicht optimal finden oder wie sie für die Frage des OP nicht relevant ist.
DavidG
3
Ich denke, die Abstimmungen sind darauf zurückzuführen, dass byte16PutStringes sich um eine Art Neuimplementierung der integrierten copyFunktion handelt, die nur das Erstellen neuer Arrays unterstützt, anstatt ein vorhandenes zu verwenden. copyhat spezielle Compiler-Unterstützung, so dass es verschiedene Arten von Argumenten verarbeiten kann, und es hat wahrscheinlich eine wirklich leistungsstarke Implementierung unter dem Deckmantel. Außerdem wurde in der Frage des OP gefragt, ob ein String in ein vorhandenes Array geschrieben werden soll, anstatt einen neuen zuzuweisen, obwohl die meisten anderen Antworten dies ebenfalls zu ignorieren scheinen ...
Jack O'Connor,
Danke @ JackO'Connor Ich bin auch hier für das Lernen und schätze das konstruktive Feedback, nicht nur die einfache Ablehnung.
DavidG
weiß nicht, y seine nach unten gestimmt answerist korrekt jeder Körper ist hier zu lernen und andere ermutigen,
Muthukumar helius
-1
Neben den oben genannten Methoden können Sie auch einen Trick ausführen
s :="hello"
b :=*(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))
Das ist verrückt. Ich denke, es lohnt sich, am Ende Ihrer Antwort "aber Sie sollten nicht" hinzuzufügen. Abgesehen von der Tatsache, dass es die Frage nicht wirklich beantwortet (OP spricht von Bytes-Array, nicht von Slices), scheinen Sie []bytemit Ihrer "Konvertierung" kein richtiges Objekt zu erhalten - es schlägt schlecht fehl, wenn Sie versuchen, Änderungen vorzunehmen p, siehe: play.golang.org/p/WHGl756ucj . In Ihrem Fall nicht sicher, warum Sie doppelt unsichere gegenüber der b := []byte(s)Methode bevorzugen würden .
Thomasz
1
@tomasz Ich ziehe es nicht vor, String <-> [] Byte auf diese Weise zu machen, sondern zeige nur eine andere Option :-) und ja, Sie haben Recht, ich habe die Frage falsch verstanden.
Brandon Gao
Wenn ich das mache, hat das Ergebnis eine cap()beliebige Größe, was bedeutet, dass es in einen unbekannten Speicher liest. Damit dies richtig ist, müssen Sie meiner Meinung nach sicherstellen, dass Sie die volle reflect.SliceHeaderGröße zuweisen und die manuell einstellen cap. So etwas wie das: play.golang.org/p/fBK4dZM-qD
Arrays sind Werte ... Slices ähneln eher Zeigern. Das ist [n]typenicht kompatibel, []typeda es sich grundsätzlich um zwei verschiedene Dinge handelt. Sie können ein Slice erhalten, das auf ein Array verweist, indem Sie arr[:]ein Slice zurückgeben, das arrals Backup-Speicher dient.
Eine Möglichkeit, ein Slice von beispielsweise []bytein zu konvertieren, besteht darin, ein Slice [20]bytezuzuweisen, [20]bytedas Sie mithilfe von verwenden können var [20]byte(da es sich um einen Wert handelt ... nicht makeerforderlich), und dann Daten darin zu kopieren:
Was viele andere Antworten falsch machen, ist, dass []typees sich NICHT um ein Array handelt.
[n]Tund []Tsind ganz andere Dinge!
Bei Verwendung von Reflect []Thandelt es sich nicht um ein Array, sondern um ein Slice und ein [n]TArray.
Sie können auch nicht verwenden, map[[]byte]Taber Sie können verwendenmap[[n]byte]T .
Dies kann manchmal umständlich sein, da beispielsweise viele Funktionen ausgeführt werden, []bytewährend einige Funktionen zurückkehren [n]byte(insbesondere die Hash-Funktionen in crypto/*). Ein sha256-Hash zum Beispiel ist [32]byteund nicht []byte, wenn Anfänger versuchen, ihn in eine Datei zu schreiben, zum Beispiel:
sum := sha256.Sum256(data)
w.Write(sum)
Sie erhalten einen Fehler. Die richtige Art zu verwenden ist
w.Write(sum[:])
Was möchten Sie jedoch? Nur byteweise auf die Zeichenfolge zugreifen? Sie können ganz einfach ein konvertieren stringzu []byteverwenden:
bytes :=[]byte(str)
Aber dies ist kein Array, es ist ein Slice. Auch byte! = rune. Wenn Sie mit "Zeichen" arbeiten möchten, müssen Sie rune... nicht verwenden byte.
str
größer als die Länge vonarr
ist, wird der Fehler "Index außerhalb des Bereichs" angezeigt.Antworten:
Sicher und einfach:
quelle
[]byte
und kein festgelegtes Byte-Array[20]byte
zu verwenden ... Glauben Sie mir nicht? Schauen Sie sich Rob Pikes Antwort auf diesen Thread an[]byte("one", "two")
?Zum Konvertieren von einer Zeichenfolge in ein Byte-Slice
string -> []byte
:Zum Konvertieren eines Arrays in ein Slice
[20]byte -> []byte
:Zum Kopieren einer Zeichenfolge in ein Array
string -> [20]byte
:Wie oben, jedoch wird die Zeichenfolge zuerst explizit in ein Slice konvertiert:
copy
Funktion nur Kopien auf eine Scheibe, aus einem Stück.[:]
die Verwendung wird ein Array als Slice qualifiziert.copy
wird nur der Teil der Zeichenfolge kopiert, der passt.Dieser Code:
... gibt folgende Ausgabe:
Ich habe es auch auf dem Go Playground zur Verfügung gestellt
quelle
b[i] = []byte("A")[0]
funktioniert, aberb[i] = 'A'
am Ende viel sauberer ist.b[1] = '本'
Zum Beispiel,
Ausgabe:
quelle
s
, Die Kopierfunktion ist nicht dumm. Anhängen an und Kopieren von Slices : "Die Anzahl der kopierten Elemente ist das Minimum von len (src) und len (dst)."Stück Kuchen:
quelle
[]byte
wird Arrays vorgezogen[20]byte
. Die Antwort ist korrekt, basierend auf Best Practices. Wenn Spezifikationen oder Code Arrays erfordern, verwenden Siecopy
stattdessen (siehe Beispiele an anderer Stelle in diesem Thread).Ich denke es ist besser..
Überprüfen Sie hier: http://play.golang.org/p/vpnAWHZZk7
quelle
Konvertieren Sie eine Zeichenfolge in ein Byte-Slice
Sie benötigen eine schnelle Möglichkeit, eine [] Zeichenfolge in einen [] Bytetyp zu konvertieren. Zur Verwendung in Situationen wie dem Speichern von Textdaten in einer Direktzugriffsdatei oder einer anderen Art der Datenmanipulation, bei der die Eingabedaten vom Typ [] Byte sein müssen.
Dies ist nützlich, wenn ioutil.WriteFile verwendet wird, das einen Byte-Slice als Datenparameter akzeptiert:
Ein anderes Beispiel
Ausgabe:
Bitte überprüfen Sie den Link Spielplatz
quelle
Am Ende wurden Array-spezifische Methoden erstellt, um dies zu tun. Ähnlich wie das Codierungs- / Binärpaket mit spezifischen Methoden für jeden int-Typ. Zum Beispiel
binary.BigEndian.PutUint16([]byte, uint16)
.Ausgabe:
Beachten Sie, wie ich links und nicht rechts auffüllen wollte.
http://play.golang.org/p/7tNumnJaiN
quelle
byte16PutString
es sich um eine Art Neuimplementierung der integriertencopy
Funktion handelt, die nur das Erstellen neuer Arrays unterstützt, anstatt ein vorhandenes zu verwenden.copy
hat spezielle Compiler-Unterstützung, so dass es verschiedene Arten von Argumenten verarbeiten kann, und es hat wahrscheinlich eine wirklich leistungsstarke Implementierung unter dem Deckmantel. Außerdem wurde in der Frage des OP gefragt, ob ein String in ein vorhandenes Array geschrieben werden soll, anstatt einen neuen zuzuweisen, obwohl die meisten anderen Antworten dies ebenfalls zu ignorieren scheinen ...answer
ist korrekt jeder Körper ist hier zu lernen und andere ermutigen,Neben den oben genannten Methoden können Sie auch einen Trick ausführen
Geh spielen: http://play.golang.org/p/xASsiSpQmC
Du solltest das niemals benutzen :-)
quelle
[]byte
mit Ihrer "Konvertierung" kein richtiges Objekt zu erhalten - es schlägt schlecht fehl, wenn Sie versuchen, Änderungen vorzunehmenp
, siehe: play.golang.org/p/WHGl756ucj . In Ihrem Fall nicht sicher, warum Sie doppelt unsichere gegenüber derb := []byte(s)
Methode bevorzugen würden .cap()
beliebige Größe, was bedeutet, dass es in einen unbekannten Speicher liest. Damit dies richtig ist, müssen Sie meiner Meinung nach sicherstellen, dass Sie die vollereflect.SliceHeader
Größe zuweisen und die manuell einstellencap
. So etwas wie das: play.golang.org/p/fBK4dZM-qDArrays sind Werte ... Slices ähneln eher Zeigern. Das ist
[n]type
nicht kompatibel,[]type
da es sich grundsätzlich um zwei verschiedene Dinge handelt. Sie können ein Slice erhalten, das auf ein Array verweist, indem Siearr[:]
ein Slice zurückgeben, dasarr
als Backup-Speicher dient.Eine Möglichkeit, ein Slice von beispielsweise
[]byte
in zu konvertieren, besteht darin, ein Slice[20]byte
zuzuweisen,[20]byte
das Sie mithilfe von verwenden könnenvar [20]byte
(da es sich um einen Wert handelt ... nichtmake
erforderlich), und dann Daten darin zu kopieren:Was viele andere Antworten falsch machen, ist, dass
[]type
es sich NICHT um ein Array handelt.[n]T
und[]T
sind ganz andere Dinge!Bei Verwendung von Reflect
[]T
handelt es sich nicht um ein Array, sondern um ein Slice und ein[n]T
Array.Sie können auch nicht verwenden,
map[[]byte]T
aber Sie können verwendenmap[[n]byte]T
.Dies kann manchmal umständlich sein, da beispielsweise viele Funktionen ausgeführt werden,
[]byte
während einige Funktionen zurückkehren[n]byte
(insbesondere die Hash-Funktionen incrypto/*
). Ein sha256-Hash zum Beispiel ist[32]byte
und nicht[]byte
, wenn Anfänger versuchen, ihn in eine Datei zu schreiben, zum Beispiel:Sie erhalten einen Fehler. Die richtige Art zu verwenden ist
Was möchten Sie jedoch? Nur byteweise auf die Zeichenfolge zugreifen? Sie können ganz einfach ein konvertieren
string
zu[]byte
verwenden:Aber dies ist kein Array, es ist ein Slice. Auch
byte
! =rune
. Wenn Sie mit "Zeichen" arbeiten möchten, müssen Sierune
... nicht verwendenbyte
.quelle