As melhores práticas de codificação no Go são usar uma fatia de bytes []bytee não uma matriz definida de bytes [20]byteao converter uma string em bytes ... Não acredita em mim? Confira a resposta de Rob Pike neste tópico
openwonk
9
O OP perguntou sobre uma matriz, não uma fatia. Em alguns casos, você precisa limitar o tamanho da fatia e usar uma matriz. Minha resposta abaixo apara os caracteres extras para garantir que você não exceda a matriz.
DavidG 14/02
3
Para aqueles que pensam que este parece um pouco estranho: esta é a conversão basta digitar Go: golang.org/ref/spec#Conversions
Cnly
alguma maneira de adicionar várias strings e concatená-las? por exemplo []byte("one", "two")?
rakim 07/02
Infelizmente não, @rakim, você só pode passar uma string ... então, você deve concatená-las primeiro ou combinar várias fatias de bytes (fora do escopo desta pergunta).
openwonk 9/02
149
Para converter de uma sequência de caracteres em uma fatia de bytes string -> []byte:
[]byte(str)
Para converter uma matriz em uma fatia [20]byte -> []byte:
arr[:]
Para copiar uma string para uma matriz string -> [20]byte:
copy(arr[:], str)
O mesmo que acima, mas convertendo explicitamente a string em uma fatia primeiro:
copy(arr[:],[]byte(str))
A copyfunção interna copia apenas para uma fatia, de uma fatia.
Matrizes são "os dados subjacentes", enquanto as fatias são "uma janela de visualização para dados subjacentes".
Usar [:]faz com que uma matriz seja qualificada como uma fatia.
Uma corda não se qualifica como uma fatia que pode ser copiado para , mas ela se qualifica como uma fatia que pode ser copiado a partir de (strings são imutáveis).
Se a sequência for muito longa, copycopia apenas a parte da sequência que se encaixa.
Este código:
var arr [20]byte
copy(arr[:],"abc")
fmt.Printf("array: %v (%T)\n", arr, arr)
Você pode querer adicionar um exemplo para converter um único caractere. Deduzi disso que b[i] = []byte("A")[0]funciona, mas b[i] = 'A'acaba sendo muito mais limpo.
Alex Jansen
11
Isso não funciona para runas de vários bytes:b[1] = '本'
Alexander
110
Por exemplo,
package main
import"fmt"
func main(){
s :="abc"var a [20]byte
copy(a[:], s)
fmt.Println("s:",[]byte(s),"a:", a)}
Esta é a única resposta que realmente aborda a pergunta original.
Jack O'Connor
Por que atribuir 20 bytes em vez de específicos sobre o que você realmente precisa para a string? Se a string precisa de menos de 20, não é um pouco ineficiente? E também propenso a erros se exceder 20?
19417 Sir
11
@ Sir: Nós não atribuímos 20 bytes. Copiamos 3 bytes, o comprimento de s, A função de cópia `não é burra. Anexando e copiando fatias : "O número de elementos copiados é o mínimo de len (src) e len (dst)."
Isso não parece estar respondendo à pergunta. O OP queria gravar os bytes da string em uma matriz existente que poderia ser maior que a string.
Jack O'Connor
2
O uso de fatias []byteé preferível às matrizes [20]byte. A resposta está correta com base nas melhores práticas; se as especificações ou o código exigirem matrizes, use-o copy(consulte exemplos em outras partes deste encadeamento).
Não é melhor Está errado. Não faz o que a pergunta pediu.
peterSO
10
Vá, converta uma string em uma fatia de bytes
Você precisa de uma maneira rápida de converter uma string [] para o tipo de byte []. Para usar em situações como armazenar dados de texto em um arquivo de acesso aleatório ou outro tipo de manipulação de dados que exija que os dados de entrada sejam do tipo [] byte.
package main
func main(){var s string//...
b :=[]byte(s)//...}
o que é útil ao usar o ioutil.WriteFile, que aceita uma fatia de bytes como parâmetro de dados:
WriteFile func(filename string, data []byte, perm os.FileMode) error
Outro exemplo
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)))}
Acabou criando métodos específicos de matriz para fazer isso. Muito parecido com o pacote de codificação / binário com métodos específicos para cada tipo int. Por exemplo 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)
Resultado:
[0000000000000979899]
Observe como eu queria estofar à esquerda, não à direita.
Se você está votando negativamente a resposta, deixe um comentário sobre por que você acha a solução não ideal ou como ela não é relevante para a pergunta do OP.
DavidG
3
Eu acho que os downvotes são porque byte16PutStringé uma espécie de reimplementação da copyfunção embutida, que apenas suporta a criação de novas matrizes em vez de usar uma existente. copypossui suporte especial ao compilador, para que ele possa lidar com diferentes tipos de argumentos e provavelmente possui uma implementação de alto desempenho oculta. Além disso, a pergunta do OP perguntou sobre a escrita de uma string para uma matriz existente, em vez de alocar um novo, embora a maioria das outras respostas parecem estar ignorando isso também ...
Jack O'Connor
Obrigado @ JackO'Connor Também estou aqui pelo aprendizado e aprecio o feedback construtivo, e não apenas o voto simples.
DavidG
não sei y seu baixo votou answerestá correto cada corpo está aqui para aprender e encorajar outros
Helius Muthukumar
-1
Além dos métodos mencionados acima, você também pode fazer um truque como
s :="hello"
b :=*(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))
Isso é loucura. Eu acho que vale a pena adicionar "mas você não deveria" ao final de sua resposta. Além do fato de ela realmente não responder à pergunta (o OP fala sobre matriz de bytes, não fatias), você não parece ter um []byteobjeto adequado usando sua "conversão" - falha muito quando tenta alterar p, consulte: play.golang.org/p/WHGl756ucj . No seu caso, não saiba por que você prefere o dobro do risco ao b := []byte(s)método.
21815
11
@tomasz Eu não prefiro fazer string <-> [] byte dessa maneira, apenas mostrando uma opção diferente :-) e sim, você está certo, eu entendi mal a pergunta.
Brandon Gao
Quando faço isso, o resultado é cap()de tamanho arbitrário, o que significa que está lendo na memória desconhecida. Para que isso seja correto, acho que você precisará alocar o reflect.SliceHeadertamanho completo e definir manualmente o cap. Algo assim: play.golang.org/p/fBK4dZM-qD
Matrizes são valores ... fatias são mais como ponteiros. Isso é[n]type não é compatível []type, pois são fundamentalmente duas coisas diferentes. Você pode obter uma fatia que aponta para uma matriz usando o arr[:]que retorna uma fatia que possui arrao fazer backup do armazenamento.
Uma maneira de converter uma fatia de, por exemplo, []bytea [20]byteé realmente alocar um [20]byteque você pode fazer usando var [20]byte(como é um valor ... nãomake necessário) e, em seguida, copiar os dados para ele:
Essencialmente, o que muitas outras respostas dão errado é que []type NÃO é uma matriz.
[n]T e []T são coisas completamente diferentes!
Ao usar refletir []T não é do tipo Array, mas do tipo Slice e [n]Té do tipo Array.
Você também não pode usar map[[]byte]T mas pode usar map[[n]byte]T.
Às vezes, isso pode ser complicado porque muitas funções operam, por exemplo, []byteenquanto algumas funções retornam [n]byte(principalmente as funções hash crypto/*). Um hash sha256, por exemplo, é [32]bytee não é []byteassim quando os iniciantes tentam gravá-lo em um arquivo, por exemplo:
sum := sha256.Sum256(data)
w.Write(sum)
eles receberão um erro. A maneira correta de usar é
w.Write(sum[:])
No entanto, o que você quer? Apenas acessando a string bytewise? Você pode facilmente converter um stringem []byte:
bytes :=[]byte(str)
mas isso não é uma matriz, é uma fatia. Além disso byte,! = rune. Caso você queira operar com "caracteres", você precisa usar rune... não byte.
str
for maior que o comprimento dearr
, você receberá um erro "índice fora do intervalo".Respostas:
Seguro e simples:
fonte
[]byte
e não uma matriz definida de bytes[20]byte
ao converter uma string em bytes ... Não acredita em mim? Confira a resposta de Rob Pike neste tópico[]byte("one", "two")
?Para converter de uma sequência de caracteres em uma fatia de bytes
string -> []byte
:Para converter uma matriz em uma fatia
[20]byte -> []byte
:Para copiar uma string para uma matriz
string -> [20]byte
:O mesmo que acima, mas convertendo explicitamente a string em uma fatia primeiro:
copy
função interna copia apenas para uma fatia, de uma fatia.[:]
faz com que uma matriz seja qualificada como uma fatia.copy
copia apenas a parte da sequência que se encaixa.Este código:
... fornece a seguinte saída:
Também disponibilizei no Go Playground
fonte
b[i] = []byte("A")[0]
funciona, masb[i] = 'A'
acaba sendo muito mais limpo.b[1] = '本'
Por exemplo,
Resultado:
fonte
s
, A função de cópia `não é burra. Anexando e copiando fatias : "O número de elementos copiados é o mínimo de len (src) e len (dst)."Pedaco de bolo:
fonte
[]byte
é preferível às matrizes[20]byte
. A resposta está correta com base nas melhores práticas; se as especificações ou o código exigirem matrizes, use-ocopy
(consulte exemplos em outras partes deste encadeamento).Eu acho melhor..
Verifique aqui: http://play.golang.org/p/vpnAWHZZk7
fonte
Vá, converta uma string em uma fatia de bytes
Você precisa de uma maneira rápida de converter uma string [] para o tipo de byte []. Para usar em situações como armazenar dados de texto em um arquivo de acesso aleatório ou outro tipo de manipulação de dados que exija que os dados de entrada sejam do tipo [] byte.
o que é útil ao usar o ioutil.WriteFile, que aceita uma fatia de bytes como parâmetro de dados:
Outro exemplo
Resultado:
Por favor, verifique o link playground
fonte
Acabou criando métodos específicos de matriz para fazer isso. Muito parecido com o pacote de codificação / binário com métodos específicos para cada tipo int. Por exemplo
binary.BigEndian.PutUint16([]byte, uint16)
.Resultado:
Observe como eu queria estofar à esquerda, não à direita.
http://play.golang.org/p/7tNumnJaiN
fonte
byte16PutString
é uma espécie de reimplementação dacopy
função embutida, que apenas suporta a criação de novas matrizes em vez de usar uma existente.copy
possui suporte especial ao compilador, para que ele possa lidar com diferentes tipos de argumentos e provavelmente possui uma implementação de alto desempenho oculta. Além disso, a pergunta do OP perguntou sobre a escrita de uma string para uma matriz existente, em vez de alocar um novo, embora a maioria das outras respostas parecem estar ignorando isso também ...answer
está correto cada corpo está aqui para aprender e encorajar outrosAlém dos métodos mencionados acima, você também pode fazer um truque como
Go Play: http://play.golang.org/p/xASsiSpQmC
Você nunca deve usar isso :-)
fonte
[]byte
objeto adequado usando sua "conversão" - falha muito quando tenta alterarp
, consulte: play.golang.org/p/WHGl756ucj . No seu caso, não saiba por que você prefere o dobro do risco aob := []byte(s)
método.cap()
de tamanho arbitrário, o que significa que está lendo na memória desconhecida. Para que isso seja correto, acho que você precisará alocar oreflect.SliceHeader
tamanho completo e definir manualmente ocap
. Algo assim: play.golang.org/p/fBK4dZM-qDMatrizes são valores ... fatias são mais como ponteiros. Isso é
[n]type
não é compatível[]type
, pois são fundamentalmente duas coisas diferentes. Você pode obter uma fatia que aponta para uma matriz usando oarr[:]
que retorna uma fatia que possuiarr
ao fazer backup do armazenamento.Uma maneira de converter uma fatia de, por exemplo,
[]byte
a[20]byte
é realmente alocar um[20]byte
que você pode fazer usandovar [20]byte
(como é um valor ... nãomake
necessário) e, em seguida, copiar os dados para ele:Essencialmente, o que muitas outras respostas dão errado é que
[]type
NÃO é uma matriz.[n]T
e[]T
são coisas completamente diferentes!Ao usar refletir
[]T
não é do tipo Array, mas do tipo Slice e[n]T
é do tipo Array.Você também não pode usar
map[[]byte]T
mas pode usarmap[[n]byte]T
.Às vezes, isso pode ser complicado porque muitas funções operam, por exemplo,
[]byte
enquanto algumas funções retornam[n]byte
(principalmente as funções hashcrypto/*
). Um hash sha256, por exemplo, é[32]byte
e não é[]byte
assim quando os iniciantes tentam gravá-lo em um arquivo, por exemplo:eles receberão um erro. A maneira correta de usar é
No entanto, o que você quer? Apenas acessando a string bytewise? Você pode facilmente converter um
string
em[]byte
:mas isso não é uma matriz, é uma fatia. Além disso
byte
,! =rune
. Caso você queira operar com "caracteres", você precisa usarrune
... nãobyte
.fonte