una - ¿Cuál es la mejor manera de agrupar recursos estáticos en un programa Go?
tareas y subtareas en project (3)
Incrustar archivos de texto
Si hablamos de archivos de texto, pueden incorporarse fácilmente en el código fuente. Simplemente use las comillas para declarar la string
literal así:
const html = `
<html>
<body>Example embedded HTML content.</body>
</html>
`
// Sending it:
w.Write([]byte(html)) // w is an io.Writer
Consejo de optimización:
Como la mayoría de las veces solo necesitará escribir el recurso en un io.Writer
, también puede almacenar el resultado de una conversión de []byte
:
var html = []byte(`
<html><body>Example...</body></html>
`)
// Sending it:
w.Write(html) // w is an io.Writer
Lo único que debe tener cuidado es que los literales de cadena sin formato no pueden contener el carácter de comillas invertidas (`). Los literales de cadena crudos no pueden contener secuencias (a diferencia de los literales de cadena interpretados), por lo que si el texto que desea incluir contiene comillas atrás, debe dividir el literal de cadena sin formato y concatenar comillas posteriores como literales de cadena interpretados, como en este ejemplo:
var html = `<p>This is a back quote followed by a dot: ` + "`" + `.</p>`
El rendimiento no se ve afectado, ya que estas compilaciones serán ejecutadas por el compilador.
Incrustar archivos binarios
Anotar como un segmento de bytes
Para los archivos binarios (por ejemplo, imágenes) más compacto (con respecto al binario nativo resultante) y más eficiente sería tener el contenido del archivo como un []byte
en el código fuente. Esto puede ser generado por toos / bibliotecas de terceros como go-bindata .
Si no desea utilizar una biblioteca de terceros para esto, aquí hay un fragmento de código simple que lee un archivo binario, y emite el código fuente Go que declara una variable de tipo []byte
que se inicializará con el contenido exacto de la archivo:
imgdata, err := ioutil.ReadFile("someimage.png")
if err != nil {
panic(err)
}
fmt.Print("var imgdata = []byte{")
for i, v := range imgdata {
if i > 0 {
fmt.Print(", ")
}
fmt.Print(v)
}
fmt.Println("}")
Ejemplo de salida si el archivo contiene bytes de 0 a 16 (pruébelo en el área de juegos Go ):
var imgdata = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
Almacenamiento como string
base64
Si el archivo no es "demasiado grande" (la mayoría de las imágenes / iconos califican), también hay otras opciones viables. Puede convertir el contenido del archivo a una string
Base64 y almacenarlo en su código fuente. Al iniciar la aplicación ( func init()
) o cuando sea necesario, puede decodificarlo al contenido original de []byte
. Go tiene un buen soporte para la codificación Base64 en el paquete de encoding/base64
.
La conversión de un archivo (binario) a una string
base64 es tan simple como:
data, err := ioutil.ReadFile("someimage.png")
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(data))
Almacene el resultado cadena base64 en su código fuente, por ejemplo, como un const
.
La decodificación es solo una llamada de función:
const imgBase64 = "<insert base64 string here>"
data, err := base64.StdEncoding.DecodeString(imgBase64) // data is of type []byte
Almacenar como una string
citada
Más eficiente que almacenar como base64, pero puede ser más largo en el código fuente, es almacenar el literal de cadena entrecomillado de los datos binarios. Podemos obtener la forma citada de cualquier cadena usando la función strconv.Quote()
:
data, err := ioutil.ReadFile("someimage.png")
if err != nil {
panic(err)
}
fmt.Println(strconv.Quote(string(data))
Para datos binarios que contienen valores desde 0 hasta 64, así es como se vería la salida (pruébelo en el campo de juego Go ):
"/x00/x01/x02/x03/x04/x05/x06/a/b/t/n/v/f/r/x0e/x0f/x10/x11/x12/x13/x14/x15/x16/x17/x18/x19/x1a/x1b/x1c/x1d/x1e/x1f !/"#$%&''()*+,-./0123456789:;<=>?"
(Tenga en cuenta que strconv.Quote()
agrega y lo antepone a comillas).
Puede usar directamente esta cadena entrecomillada en su código fuente, por ejemplo:
const imgdata = "/x00/x01/x02/x03/x04/x05/x06/a/b/t/n/v/f/r/x0e/x0f/x10/x11/x12/x13/x14/x15/x16/x17/x18/x19/x1a/x1b/x1c/x1d/x1e/x1f !/"#$%&''()*+,-./0123456789:;<=>?"
Está listo para usar, no es necesario decodificarlo; el comparador Go realiza el desvinculación en el momento de la compilación.
También puede almacenarlo como un segmento de bytes si lo necesita así:
var imgdata = []byte("/x00/x01/x02/x03/x04/x05/x06/a/b/t/n/v/f/r/x0e/x0f/x10/x11/x12/x13/x14/x15/x16/x17/x18/x19/x1a/x1b/x1c/x1d/x1e/x1f !/"#$%&''()*+,-./0123456789:;<=>?")
Estoy trabajando en una pequeña aplicación web en Go que pretende ser utilizada como una herramienta en una máquina de desarrollador para ayudar a depurar sus aplicaciones / servicios web. La interfaz del programa es una página web que incluye no solo el HTML, sino también JavaScript (para la funcionalidad), imágenes y CSS (para el estilo). Estoy planeando abrir esta aplicación para que los usuarios puedan simplemente ejecutar un archivo Makefile y todos los recursos irán donde necesiten ir. Sin embargo, también me gustaría poder simplemente distribuir un archivo ejecutable con la menor cantidad de archivos / dependencias posible. ¿Hay una buena manera de agrupar el HTML / CSS / JS con el ejecutable, por lo que los usuarios solo tienen que descargar y preocuparse por un archivo?
En este momento, en mi aplicación, al servir un archivo estático se ve un poco así:
// called via http.ListenAndServe
func switchboard(w http.ResponseWriter, r *http.Request) {
// snipped dynamic routing...
// look for static resource
uri := r.URL.RequestURI()
if fp, err := os.Open("static" + uri); err == nil {
defer fp.Close()
staticHandler(w, r, fp)
return
}
// snipped blackhole route
}
Así que es bastante simple: si el archivo solicitado existe en mi directorio estático, invoque el controlador, que simplemente abre el archivo e intenta establecer un buen tipo de Content-Type
antes de servirlo. Mi idea era que no hay ninguna razón para que esto tenga que basarse en el sistema de archivos real: si hubiera recursos compilados, simplemente podría indexarlos mediante el URI de solicitud y servirlos como tales.
Si no hay una buena manera de hacerlo, o estoy ladrando al árbol equivocado al intentar hacer esto, házmelo saber. Pensé que el usuario final apreciaría la menor cantidad de archivos posible para administrar.
Si hay más etiquetas apropiadas que go , siéntase libre de agregarlas o avisarme.
El paquete go-bindata parece que podría ser lo que le interesa.
https://github.com/go-bindata/go-bindata
Le permitirá convertir cualquier archivo estático en una llamada de función que pueda integrarse en su código y devolverá un segmento de bytes del contenido del archivo cuando se le llame.
también hay una forma exótica: uso el plugin maven para construir proyectos GoLang y permite usar el preprocesador JCP para incrustar bloques binarios y archivos de texto en las fuentes. En el código del caso, simplemente mire la línea siguiente ( y algunos ejemplos se pueden encontrar aquí )
var imageArray = []uint8{/*$binfile("./image.png","uint8[]")$*/}