Tengo un io.ReadCloser
objeto (de un http.Response
objeto).
¿Cuál es la forma más eficiente de convertir toda la secuencia en un string
objeto?
EDITAR:
Desde 1.10, strings.Builder existe. Ejemplo:
buf := new(strings.Builder)
n, err := io.Copy(buf, r)
// check errors
fmt.Println(buf.String())
INFORMACIÓN ACTUALIZADA A CONTINUACIÓN
La respuesta corta es que no será eficiente porque la conversión a una cadena requiere hacer una copia completa de la matriz de bytes. Aquí está la forma adecuada (no eficiente) de hacer lo que quiere:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
s := buf.String() // Does a complete copy of the bytes in the buffer.
Esta copia se realiza como un mecanismo de protección. Las cuerdas son inmutables. Si pudiera convertir un byte [] en una cadena, podría cambiar el contenido de la cadena. Sin embargo, go le permite deshabilitar los mecanismos de seguridad de tipo utilizando el paquete inseguro. Utilice el paquete inseguro bajo su propio riesgo. Esperemos que solo el nombre sea una advertencia lo suficientemente buena. Así es como lo haría usando inseguro:
buf := new(bytes.Buffer)
buf.ReadFrom(yourReader)
b := buf.Bytes()
s := *(*string)(unsafe.Pointer(&b))
Ahí vamos, ahora ha convertido eficientemente su conjunto de bytes en una cadena. Realmente, todo lo que hace es engañar al sistema de tipos para que lo llame cadena. Hay un par de advertencias para este método:
Mi consejo es seguir el método oficial. Hacer una copia no es que caro y no vale la pena los males de la insegura. Si la cadena es demasiado grande para hacer una copia, no debería convertirla en una cadena.
strings.Builder
hace esto de manera eficiente al garantizar que el subyacente[]byte
nunca se filtre y convertirlostring
sin una copia de una manera que sea compatible en el futuro. Esto no existía en 2012. La solución de @ dimchansky a continuación ha sido la correcta desde Go 1.10. Por favor considere una edición!Las respuestas hasta ahora no han abordado la parte "completa de la secuencia" de la pregunta. Creo que la buena manera de hacer esto es
ioutil.ReadAll
. Con tuio.ReaderCloser
nombrerc
, escribiríafuente
buf.ReadFrom()
también lee todo el flujo hasta EOF.ioutil.ReadAll()
y simplemente se ajusta unbytes.Buffer
'sReadFrom
. Y elString()
método del búfer es una simple envoltura para transmitir, porstring
lo que los dos enfoques son prácticamente iguales.fuente
La forma más eficiente sería usar siempre en
[]byte
lugar destring
.En caso de tener que imprimir los datos recibidos desde el
io.ReadCloser
, elfmt
paquete puede manejar[]byte
, pero no es eficiente debido a que lafmt
aplicación va a convertir internamente[]byte
astring
. Para evitar esta conversión, puede implementar lafmt.Formatter
interfaz para un tipo comotype ByteSlice []byte
.fuente
[]byte
astring
es razonablemente rápida, pero la pregunta era "la forma más eficiente". Actualmente, el tiempo de ejecución de Go siempre asignará uno nuevostring
al convertir[]byte
astring
. La razón de esto es que el compilador no sabe cómo determinar si[]byte
se modificará después de la conversión. Aquí hay espacio para optimizaciones del compilador.fuente
fuente
Me gusta la estructura bytes.Buffer . Veo que tiene métodos ReadFrom y String . Lo he usado con un byte [] pero no un io.Reader.
fuente