Las mejores prácticas de codificación en Go son usar una porción de bytes []bytey no una matriz de bytes establecida [20]byteal convertir una cadena a bytes ... ¿No me crees? Echa un vistazo a la respuesta de Rob Pike en este hilo
openwonk
99
El OP preguntó sobre una matriz, no un segmento. En algunos casos, debe limitar el tamaño del segmento y utilizar una matriz en su lugar. Mi respuesta a continuación recorta los caracteres adicionales para asegurarse de que no desborde la matriz.
DavidG
3
Para aquellos que piensan que esto parece un poco extraño: esto es solo conversión de tipo en Go: golang.org/ref/spec#Conversions
Cnly
¿alguna forma de agregar múltiples cadenas y concatenarlas? por ejemplo []byte("one", "two")?
rakim
Desafortunadamente no, @rakim, solo puede pasar una cadena ... por lo tanto, primero debe concatenarlas o combinar varios segmentos de bytes (fuera del alcance de esta pregunta).
openwonk
149
Para la conversión de una cadena a una rebanada de bytes, string -> []byte:
[]byte(str)
Para convertir una matriz en un segmento [20]byte -> []byte:
arr[:]
Para copiar una cadena a una matriz string -> [20]byte:
copy(arr[:], str)
Igual que el anterior, pero primero convierte explícitamente la cadena en un segmento:
copy(arr[:],[]byte(str))
La copyfunción incorporada solo copia en un segmento, desde un segmento.
Las matrices son "los datos subyacentes", mientras que los segmentos son "una ventana gráfica a los datos subyacentes".
El uso [:]hace que una matriz califique como un segmento.
Una cadena no califica como una rebanada que se puede copiar a , pero califica como una rebanada que se puede copiar a partir de (las cadenas son inmutables).
Si la cadena es demasiado larga, copysolo copiará la parte de la cadena que se ajuste.
Este código:
var arr [20]byte
copy(arr[:],"abc")
fmt.Printf("array: %v (%T)\n", arr, arr)
Es posible que desee agregar un ejemplo para convertir un solo carácter. De esto deduje que b[i] = []byte("A")[0]funciona, pero b[i] = 'A'termina siendo mucho más limpio.
Alex Jansen
1
Eso no funciona para runas de varios bytes:b[1] = '本'
Alexander
110
Por ejemplo,
package main
import"fmt"
func main(){
s :="abc"var a [20]byte
copy(a[:], s)
fmt.Println("s:",[]byte(s),"a:", a)}
Esta es la única respuesta que realmente aborda la pregunta original.
Jack O'Connor
¿Por qué asignar 20 bytes en lugar de lo específico que realmente necesita para la cadena? Si la cadena necesita menos de 20, ¿no es un poco ineficiente? ¿Y también propenso a errores si supera los 20?
Sir
1
@Sir: No asignamos 20 bytes. Copiamos 3 bytes, la longitud de s, `La función de copia no es tonta. Agregar y copiar segmentos : "El número de elementos copiados es el mínimo de len (src) y len (dst)".
Esto no parece estar respondiendo la pregunta. OP quería escribir los bytes de la cadena en una matriz existente que podría ser más larga que la cadena.
Jack O'Connor
2
[]byteSe prefiere el uso de rebanadas sobre las matrices [20]byte. La respuesta es correcta según las mejores prácticas; si las especificaciones o el código requieren matrices, utilícelas copyen su lugar (consulte los ejemplos en este hilo).
No es mejor Está incorrecto. No hace lo que pedía la pregunta.
peterSO
10
Ir, convertir una cadena en un segmento de bytes
Necesita una forma rápida de convertir una cadena [] a un tipo de byte. Para usar en situaciones como el almacenamiento de datos de texto en un archivo de acceso aleatorio u otro tipo de manipulación de datos que requiera que los datos de entrada estén en tipo [] byte.
package main
func main(){var s string//...
b :=[]byte(s)//...}
que es útil cuando se usa ioutil.WriteFile, que acepta un segmento de bytes como parámetro de datos:
WriteFile func(filename string, data []byte, perm os.FileMode) error
Otro ejemplo
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)))}
Terminé creando métodos específicos de matriz para hacer esto. Al igual que el paquete de codificación / binario con métodos específicos para cada tipo int. Por ejemplo 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)
Salida:
[0000000000000979899]
Observe cómo quería relleno a la izquierda, no a la derecha.
Si no está votando la respuesta, deje un comentario sobre por qué considera que la solución no es óptima o cómo no es relevante para la pregunta del OP.
DavidG
3
Creo que los votos negativos se deben a que byte16PutStringes una especie de reimplementación de la copyfunción incorporada , que solo admite la creación de nuevas matrices en lugar de utilizar una existente. copytiene un soporte especial para el compilador, por lo que puede manejar diferentes tipos de argumentos, y probablemente tenga una implementación de alto rendimiento bajo las cubiertas. Además, la pregunta del OP se refería a escribir una cadena en una matriz existente, en lugar de asignar una nueva, aunque la mayoría de las otras respuestas parecen ignorar eso también ...
Jack O'Connor
Gracias @ JackO'Connor También estoy aquí por el aprendizaje y aprecio los comentarios constructivos, no solo el simple voto negativo.
DavidG
No sé si su answer
voto negativo
-1
Además de los métodos mencionados anteriormente, también puedes hacer un truco como
s :="hello"
b :=*(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))
Esto es Loco. Creo que vale la pena agregar "pero no deberías" al final de tu respuesta. Aparte del hecho de que realmente no responde a la pregunta (OP habla de la matriz de bytes, no de las rebanadas), parece que no obtiene un []byteobjeto adecuado utilizando su "conversión"; falla gravemente cuando intenta modificar p, vea: play.golang.org/p/WHGl756ucj . En su caso, no estoy seguro de por qué preferiría doble inseguro sobre el b := []byte(s)método.
tomasz
1
@tomasz No prefiero hacer el string <-> [] byte de esta manera, solo mostrando una opción diferente :-) y sí, tienes razón, no entendí la pregunta.
Brandon Gao
Cuando hago esto, el resultado tiene un cap()tamaño arbitrario, lo que significa que está leyendo en memoria desconocida. Para que esto sea correcto, creo que debe asegurarse de asignar el reflect.SliceHeadertamaño completo y configurarlo manualmente cap. Algo como esto: play.golang.org/p/fBK4dZM-qD
Las matrices son valores ... las rebanadas son más como punteros. Eso [n]typeno es compatible, []typeya que son fundamentalmente dos cosas diferentes. Puede obtener un segmento que apunte a una matriz mediante el uso arr[:]que devuelve un segmento que tiene arrcomo respaldo de almacenamiento.
Una forma de convertir un trozo de, por ejemplo, []bytea [20]bytees asignar en realidad una [20]byteque se puede hacer mediante el uso var [20]byte(ya que es un valor ... no makees necesario) y luego copiar datos en él:
Esto a veces puede ser engorroso porque muchas funciones funcionan, por ejemplo, []bytemientras que algunas funciones regresan [n]byte(más notablemente las funciones hash en crypto/*). Un hash sha256, por ejemplo, es [32]bytey no es []byteasí cuando los principiantes intentan escribirlo en un archivo, por ejemplo:
sum := sha256.Sum256(data)
w.Write(sum)
obtendrán un error. La forma correcta de usar
w.Write(sum[:])
Sin embargo, ¿qué es lo que quieres? ¿Solo accediendo a la cadena bytewise? Puede convertir fácilmente un stringa []byteusando:
bytes :=[]byte(str)
pero esto no es una matriz, es un segmento. Además byte,! = rune. En caso de que desee operar con "personajes", debe usar rune... no byte.
str
es mayor que la longitud dearr
, obtendrá un error de "índice fuera de rango".Respuestas:
Seguro y simple:
fuente
[]byte
y no una matriz de bytes establecida[20]byte
al convertir una cadena a bytes ... ¿No me crees? Echa un vistazo a la respuesta de Rob Pike en este hilo[]byte("one", "two")
?Para la conversión de una cadena a una rebanada de bytes,
string -> []byte
:Para convertir una matriz en un segmento
[20]byte -> []byte
:Para copiar una cadena a una matriz
string -> [20]byte
:Igual que el anterior, pero primero convierte explícitamente la cadena en un segmento:
copy
función incorporada solo copia en un segmento, desde un segmento.[:]
hace que una matriz califique como un segmento.copy
solo copiará la parte de la cadena que se ajuste.Este código:
... da el siguiente resultado:
También lo hice disponible en Go Playground
fuente
b[i] = []byte("A")[0]
funciona, perob[i] = 'A'
termina siendo mucho más limpio.b[1] = '本'
Por ejemplo,
Salida:
fuente
s
, `La función de copia no es tonta. Agregar y copiar segmentos : "El número de elementos copiados es el mínimo de len (src) y len (dst)".Pedazo de pastel:
fuente
[]byte
Se prefiere el uso de rebanadas sobre las matrices[20]byte
. La respuesta es correcta según las mejores prácticas; si las especificaciones o el código requieren matrices, utilícelascopy
en su lugar (consulte los ejemplos en este hilo).Yo pienso que es mejor..
Consulta aquí: http://play.golang.org/p/vpnAWHZZk7
fuente
Ir, convertir una cadena en un segmento de bytes
Necesita una forma rápida de convertir una cadena [] a un tipo de byte. Para usar en situaciones como el almacenamiento de datos de texto en un archivo de acceso aleatorio u otro tipo de manipulación de datos que requiera que los datos de entrada estén en tipo [] byte.
que es útil cuando se usa ioutil.WriteFile, que acepta un segmento de bytes como parámetro de datos:
Otro ejemplo
Salida:
Por favor revise el enlace del patio de recreo
fuente
Terminé creando métodos específicos de matriz para hacer esto. Al igual que el paquete de codificación / binario con métodos específicos para cada tipo int. Por ejemplo
binary.BigEndian.PutUint16([]byte, uint16)
.Salida:
Observe cómo quería relleno a la izquierda, no a la derecha.
http://play.golang.org/p/7tNumnJaiN
fuente
byte16PutString
es una especie de reimplementación de lacopy
función incorporada , que solo admite la creación de nuevas matrices en lugar de utilizar una existente.copy
tiene un soporte especial para el compilador, por lo que puede manejar diferentes tipos de argumentos, y probablemente tenga una implementación de alto rendimiento bajo las cubiertas. Además, la pregunta del OP se refería a escribir una cadena en una matriz existente, en lugar de asignar una nueva, aunque la mayoría de las otras respuestas parecen ignorar eso también ...answer
Además de los métodos mencionados anteriormente, también puedes hacer un truco como
Ir a jugar: http://play.golang.org/p/xASsiSpQmC
Nunca deberías usar esto :-)
fuente
[]byte
objeto adecuado utilizando su "conversión"; falla gravemente cuando intenta modificarp
, vea: play.golang.org/p/WHGl756ucj . En su caso, no estoy seguro de por qué preferiría doble inseguro sobre elb := []byte(s)
método.cap()
tamaño arbitrario, lo que significa que está leyendo en memoria desconocida. Para que esto sea correcto, creo que debe asegurarse de asignar elreflect.SliceHeader
tamaño completo y configurarlo manualmentecap
. Algo como esto: play.golang.org/p/fBK4dZM-qDLas matrices son valores ... las rebanadas son más como punteros. Eso
[n]type
no es compatible,[]type
ya que son fundamentalmente dos cosas diferentes. Puede obtener un segmento que apunte a una matriz mediante el usoarr[:]
que devuelve un segmento que tienearr
como respaldo de almacenamiento.Una forma de convertir un trozo de, por ejemplo,
[]byte
a[20]byte
es asignar en realidad una[20]byte
que se puede hacer mediante el usovar [20]byte
(ya que es un valor ... nomake
es necesario) y luego copiar datos en él:Esencialmente, lo que muchas otras respuestas se equivocan es que
[]type
NO es una matriz.[n]T
y[]T
son cosas completamente diferentes!Cuando se utiliza el reflejo,
[]T
no es de tipo Array sino de tipo Slice y[n]T
es de tipo Array.Tampoco puedes usar
map[[]byte]T
pero puedes usarmap[[n]byte]T
.Esto a veces puede ser engorroso porque muchas funciones funcionan, por ejemplo,
[]byte
mientras que algunas funciones regresan[n]byte
(más notablemente las funciones hash encrypto/*
). Un hash sha256, por ejemplo, es[32]byte
y no es[]byte
así cuando los principiantes intentan escribirlo en un archivo, por ejemplo:obtendrán un error. La forma correcta de usar
Sin embargo, ¿qué es lo que quieres? ¿Solo accediendo a la cadena bytewise? Puede convertir fácilmente un
string
a[]byte
usando:pero esto no es una matriz, es un segmento. Además
byte
,! =rune
. En caso de que desee operar con "personajes", debe usarrune
... nobyte
.fuente