Come assegnare una stringa all'array di byte


375

Voglio assegnare una stringa all'array di byte:

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

Hai un altro metodo?


11
Se la lunghezza di strè maggiore della lunghezza di arrallora si otterrà un errore "indice fuori intervallo".
peterSO,

Risposte:


544

Sicuro e semplice:

[]byte("Here is a string....")

14
Le migliori pratiche di codifica in Go utilizzano una porzione di byte []bytee non una serie di byte [20]bytequando si converte una stringa in byte ... Non mi credi?
Dai un'occhiata

9
L'OP ha chiesto un array, non una sezione. In alcuni casi è necessario limitare la dimensione della sezione e utilizzare invece un array. La mia risposta di seguito consente di tagliare i caratteri aggiuntivi per assicurarsi di non traboccare l'array.
DavidG

3
Per coloro che pensano che questo appaia un po 'strano: questa è solo la conversione del tipo in Go: golang.org/ref/spec#Conversions
Cnly,

un modo per aggiungere più stringhe e farle concatenare? ad es []byte("one", "two").
Rakim

Sfortunatamente no, @rakim, puoi passare solo una stringa ... quindi, devi prima concatenarli o combinare più sezioni di byte (al di fuori dell'ambito di questa domanda).
openwonk

149

Per la conversione da una stringa a una fetta di byte, string -> []byte:

[]byte(str)

Per convertire un array in una sezione [20]byte -> []byte:

arr[:]

Per la copia di una stringa in un array, string -> [20]byte:

copy(arr[:], str)

Come sopra, ma prima converti esplicitamente la stringa in una sezione:

copy(arr[:], []byte(str))

  • La copyfunzione integrata copia solo in una sezione, da una sezione.
  • Le matrici sono "i dati sottostanti", mentre le sezioni sono "una finestra nei dati sottostanti".
  • L'utilizzo [:]rende un array idoneo come slice.
  • Una stringa non si qualifica come una fetta che può essere copiato da , ma si qualifica come una fetta che può essere copiato da (stringhe sono immutabili).
  • Se la stringa è troppo lunga, copycopierà solo la parte della stringa adatta.

Questo codice:

var arr [20]byte
copy(arr[:], "abc")
fmt.Printf("array: %v (%T)\n", arr, arr)

... fornisce il seguente output:

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

L'ho anche reso disponibile al Go Playground


Potresti voler aggiungere un esempio per convertire un singolo carattere. Ne ho dedotto che b[i] = []byte("A")[0]funziona, ma b[i] = 'A'finisce per essere molto più pulito.
Alex Jansen,

1
Questo non funziona per le rune multi-byte:b[1] = '本'
Alexander

110

Per esempio,

package main

import "fmt"

func main() {
    s := "abc"
    var a [20]byte
    copy(a[:], s)
    fmt.Println("s:", []byte(s), "a:", a)
}

Produzione:

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]

3
Questa è l'unica risposta che risponde effettivamente alla domanda originale.
Jack O'Connor,

Perché assegnare 20 byte piuttosto che specifici su di te effettivamente necessari per la stringa? Se la stringa ha bisogno di meno di 20 non è un po 'inefficiente? E anche soggetto a errori se supera i 20?
Sir

1
@Sir: non assegniamo 20 byte. Copiamo 3 byte, la lunghezza di s, La funzione `copia non è stupida. Aggiunta e copia di sezioni : "Il numero di elementi copiati è il minimo di len (src) e len (dst)."
peterSO,

42

Pezzo di torta:

arr := []byte("That's all folks!!")

8
Questo non sembra rispondere alla domanda. OP voleva scrivere i byte della stringa su un array esistente che potrebbe essere più lungo della stringa.
Jack O'Connor,

2
L'uso delle sezioni []byteè preferito rispetto alle matrici [20]byte. La risposta è corretta in base alle migliori pratiche; se le specifiche o il codice richiedono matrici, utilizzare copyinvece (vedere esempi altrove in questo thread).
openwonk,


10

Vai, converti una stringa in una porzione di byte

È necessario un modo rapido per convertire una stringa [] nel tipo di byte []. Da utilizzare in situazioni come l'archiviazione di dati di testo in un file ad accesso casuale o un altro tipo di manipolazione dei dati che richiede che i dati di input siano nel tipo di byte [].

package main

func main() {

    var s string

    //...

    b := []byte(s)

    //...
}

che è utile quando si utilizza ioutil.WriteFile, che accetta una porzione di byte come parametro di dati:

WriteFile func(filename string, data []byte, perm os.FileMode) error

Un altro esempio

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

Produzione:

[104 101 108 108 111 32 119 111 114 108 100] ciao mondo

Si prega di controllare il parco giochi di collegamento


0

Ho finito per creare metodi specifici dell'array per fare questo. Proprio come il pacchetto di codifica / binario con metodi specifici per ogni tipo di int. Per esempio 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)

Produzione:

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

Notate come volevo imbottitura a sinistra, non a destra.

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


3
Se stai votando in negativo la risposta, lascia un commento sul motivo per cui ritieni che la soluzione non sia ottimale o in che modo non sia pertinente alla domanda del PO.
DavidG,

3
Penso che i downvotes siano perché byte16PutStringè una sorta di reimplementazione della copyfunzione built-in , che supporta solo la creazione di nuove matrici invece di usarne una esistente. copyha un supporto compilatore speciale, quindi può gestire diversi tipi di argomenti e probabilmente ha un'implementazione ad alte prestazioni sotto le coperte. Inoltre, la domanda del PO ha posto la domanda di scrivere una stringa su un array esistente, piuttosto che assegnarne uno nuovo, anche se la maggior parte delle altre risposte sembra ignorare anche questo ...
Jack O'Connor,

Grazie @ JackO'Connor Sono qui anche per l'apprendimento e apprezzo il feedback costruttivo, non solo il semplice voto negativo.
DavidG

non so che il suo voto answer
negativo

-1

Oltre ai metodi sopra menzionati, puoi anche fare un trucco come

s := "hello"
b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))

Vai a giocare: http://play.golang.org/p/xASsiSpQmC

Non dovresti mai usare questo :-)


1
Questo è pazzesco. Penso che valga la pena aggiungere "ma non dovresti" alla fine della tua risposta. A parte il fatto che in realtà non risponde alla domanda (OP parla di array di byte, non di slice), sembra che non si ottenga un []byteoggetto corretto usando la "conversione" - fallisce male quando si tenta di modificare p, vedere: play.golang.org/p/WHGl756ucj . Nel tuo caso, non sono sicuro del motivo per cui preferiresti doppio non sicuro rispetto al b := []byte(s)metodo.
Tomasz,

1
@tomasz Non preferisco fare stringa <-> [] byte in questo modo, mostrando solo un'opzione diversa :-) e sì hai ragione, ho frainteso la domanda.
Brandon Gao,

Quando lo faccio, il risultato ha una cap()dimensione arbitraria, il che significa che sta leggendo nella memoria sconosciuta. Perché questo sia corretto, penso che dovresti assicurarti di allocare le reflect.SliceHeaderdimensioni complete e impostare manualmente il cap. Qualcosa del genere: play.golang.org/p/fBK4dZM-qD
Lye Fish

E non ne sono nemmeno certo .------------- ^ - Forse è meglio: play.golang.org/p/NJUxb20FTG
Lye Fish

-1

Le matrici sono valori ... le sezioni sono più simili a puntatori. Ciò [n]typenon è compatibile []typein quanto fondamentalmente sono due cose diverse. È possibile ottenere una sezione che punta a un array utilizzando arr[:]quale restituisce una sezione che haarr come supporto di archiviazione.

Un modo per convertire una fetta di per esempio []byteper [20]byteè quello di allocare in realtà una [20]byteche si può fare utilizzando var [20]byte(come è un valore ... non makenecessario) e poi copiare i dati in esso:

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

In sostanza, molte altre risposte sbagliate []typenon sono un array.

[n]Te []Tsono cose completamente diverse!

Quando si utilizza reflect []Tnon è di tipo Array ma di tipo Slice e[n]T è di tipo Array.

Inoltre non puoi usare map[[]byte]Tma puoi usaremap[[n]byte]T .

Questo a volte può essere ingombrante perché molte funzioni operano ad esempio []bytementre alcune funzioni ritornano [n]byte(in particolare le funzioni hash in crypto/*). Un hash sha256 per esempio è [32]bytee non è []bytecosì quando i principianti provano a scriverlo in un file per esempio:

sum := sha256.Sum256(data)
w.Write(sum)

riceveranno un errore. Il modo corretto di è usare

w.Write(sum[:])

Tuttavia, che cosa vuoi? Stai solo accedendo alla stringa in senso byte? Puoi facilmente convertire un stringin []byteusando:

bytes := []byte(str)

ma questo non è un array, è una fetta. Inoltre byte,! = rune. Nel caso tu voglia operare su "personaggi" devi usare rune... no byte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.