Respuestas:
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 convertirlo string
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 tu io.ReaderCloser
nombre rc
, escribiría
if b, err := ioutil.ReadAll(rc); err == nil {
return string(b)
} ...
buf.ReadFrom()
también lee todo el flujo hasta EOF.
ioutil.ReadAll()
y simplemente se ajusta un bytes.Buffer
's ReadFrom
. Y el String()
método del búfer es una simple envoltura para transmitir, por string
lo que los dos enfoques son prácticamente iguales.
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
La forma más eficiente sería usar siempre en []byte
lugar de string
.
En caso de tener que imprimir los datos recibidos desde el io.ReadCloser
, el fmt
paquete puede manejar []byte
, pero no es eficiente debido a que la fmt
aplicación va a convertir internamente []byte
a string
. Para evitar esta conversión, puede implementar la fmt.Formatter
interfaz para un tipo como type ByteSlice []byte
.
[]byte
a string
es razonablemente rápida, pero la pregunta era "la forma más eficiente". Actualmente, el tiempo de ejecución de Go siempre asignará uno nuevo string
al convertir []byte
a string
. 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.
func copyToString(r io.Reader) (res string, err error) {
var sb strings.Builder
if _, err = io.Copy(&sb, r); err == nil {
res = sb.String()
}
return
}
var b bytes.Buffer
b.ReadFrom(r)
// b.String()
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.