So weisen Sie dem Byte-Array eine Zeichenfolge zu

375

Ich möchte dem Bytes-Array einen String zuweisen:

var arr [20]byte
str := "abc"
for k, v := range []byte(str) {
  arr[k] = byte(v)
}

Haben Sie eine andere Methode?

Sofire
quelle
11
Wenn die Länge von strgrößer als die Länge von arrist, wird der Fehler "Index außerhalb des Bereichs" angezeigt.
PeterSO

Antworten:

543

Sicher und einfach:

[]byte("Here is a string....")
openwonk
quelle
14
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)

... gibt folgende Ausgabe:

array: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] ([20]uint8)

Ich habe es auch auf dem Go Playground zur Verfügung gestellt

Alexander
quelle
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)
}

Ausgabe:

s: [97 98 99] a: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
peterSO
quelle
3
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)."
PeterSO
42

Stück Kuchen:

arr := []byte("That's all folks!!")
Sameh Sharaf
quelle
8
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).
openwonk
25

Ich denke es ist besser..

package main

import "fmt"

func main() {
    str := "abc"
    mySlice := []byte(str)
    fmt.Printf("%v -> '%s'",mySlice,mySlice )
}

Überprüfen Sie hier: http://play.golang.org/p/vpnAWHZZk7

Chespinoza
quelle
3
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)))
}

Ausgabe:

[104 101 108 108 111 32 119 111 114 108 100] Hallo Welt

Bitte überprüfen Sie den Link Spielplatz

ASHWIN RAJEEV
quelle
0

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]byte
    if 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:

[0 0 0 0 0 0 0 0 0 0 0 0 0 97 98 99]

Beachten Sie, wie ich links und nicht rechts auffüllen wollte.

http://play.golang.org/p/7tNumnJaiN

DavidG
quelle
3
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))))

Geh spielen: http://play.golang.org/p/xASsiSpQmC

Du solltest das niemals benutzen :-)

Brandon Gao
quelle
1
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
Lye Fish
Und da bin ich mir nicht mal sicher .------------- ^ - Vielleicht ist das besser: play.golang.org/p/NJUxb20FTG
Lye Fish
-1

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:

buf := make([]byte, 10)
var arr [10]byte
copy(arr[:], buf)

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.

mroman
quelle