Saya sedang mengerjakan aplikasi web kecil di Go yang dimaksudkan untuk digunakan sebagai alat pada mesin pengembang untuk membantu men-debug aplikasi / layanan web mereka. Antarmuka ke program adalah halaman web yang tidak hanya mencakup HTML, tetapi beberapa JavaScript (untuk fungsionalitas), gambar dan CSS (untuk gaya). Saya berencana untuk membuat aplikasi ini menjadi sumber terbuka, jadi pengguna harus dapat menjalankan Makefile dan semua sumber daya akan pergi ke mana pun mereka harus pergi. Namun, saya juga ingin dapat mendistribusikan file yang dapat dieksekusi dengan sesedikit mungkin file / dependensi. Apakah ada cara yang baik untuk memaketkan HTML / CSS / JS dengan yang dapat dieksekusi, sehingga pengguna hanya perlu mengunduh dan mengkhawatirkan satu file?
Saat ini, di aplikasi saya, menyajikan file statis terlihat seperti ini:
// 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
}
Jadi cukup sederhana: jika file yang diminta ada di direktori statis saya, panggil handler, yang akan membuka file tersebut dan mencoba mengatur kebaikan Content-Type
sebelum disajikan. Pemikiran saya adalah bahwa tidak ada alasan ini perlu didasarkan pada sistem file yang sebenarnya: jika ada sumber daya yang dikompilasi, saya dapat mengindeksnya dengan URI permintaan dan melayani mereka seperti itu.
Jika tidak ada cara yang baik untuk melakukan ini, atau saya menggonggong pohon yang salah dengan mencoba melakukan ini, beri tahu saya. Saya baru saja membayangkan pengguna akhir akan menghargai sesedikit mungkin file untuk dikelola.
Jika ada lebih banyak tag yang sesuai daripada Pergilah, jangan ragu untuk menambahkannya atau beri tahu saya.
go generate
utilitas baris perintah kecil (dikemas dengan kode sumber saya) untuk mengonversi file menjadi[]byte
irisan yang disematkan sebagai variabel dalam kode, mirip dengan bagaimanastringer
melakukannya (lihat blog.golang.org / hasilkan ).Jawaban:
Paket go-bindata sepertinya sesuai dengan minat Anda.
https://github.com/go-bindata/go-bindata
Ini akan memungkinkan Anda untuk mengonversi file statis apa pun menjadi panggilan fungsi yang dapat disematkan dalam kode Anda dan akan mengembalikan potongan byte dari konten file saat dipanggil.
sumber
Menyematkan File Teks
Jika kita berbicara tentang file teks, mereka dapat dengan mudah disematkan di kode sumber itu sendiri. Cukup gunakan tanda kutip belakang untuk menyatakan
string
literal seperti ini:Tip pengoptimalan:
Karena sebagian besar waktu Anda hanya perlu menulis sumber daya ke
io.Writer
, Anda juga dapat menyimpan hasil[]byte
konversi:Satu-satunya hal yang harus Anda perhatikan adalah literal string mentah tidak boleh berisi karakter kutipan belakang (`). Literal string mentah tidak boleh berisi urutan (tidak seperti literal string yang ditafsirkan), jadi jika teks yang ingin Anda sematkan memang berisi tanda kutip balik, Anda harus menghentikan literal string mentah dan menggabungkan tanda kutip kembali sebagai literal string yang ditafsirkan, seperti dalam contoh ini:
Performa tidak terpengaruh, karena penggabungan ini akan dijalankan oleh kompilator.
Menyematkan File Biner
Menyimpan sebagai potongan byte
Untuk file biner (mis. Gambar) yang paling ringkas (berkenaan dengan biner asli yang dihasilkan) dan paling efisien adalah memiliki konten file sebagai
[]byte
dalam kode sumber Anda. Ini dapat dibuat oleh toos / library pihak ketiga seperti go-bindata .Jika Anda tidak ingin menggunakan pustaka pihak ketiga untuk ini, berikut cuplikan kode sederhana yang membaca file biner, dan mengeluarkan kode sumber Go yang mendeklarasikan variabel jenis
[]byte
yang akan diinisialisasi dengan konten file yang tepat:Contoh keluaran jika file akan berisi byte dari 0 hingga 16 (coba di Go Playground ):
Menyimpan sebagai base64
string
Jika file tidak "terlalu besar" (kebanyakan gambar / ikon memenuhi syarat), ada opsi lain yang layak juga. Anda dapat mengonversi konten file ke Base64
string
dan menyimpannya di kode sumber Anda. Saat aplikasi dimulai (func init()
) atau saat diperlukan, Anda bisa mendekodekannya ke[]byte
konten asli . Go memiliki dukungan yang bagus untuk pengkodean Base64 dalamencoding/base64
paket.Mengonversi file (biner) ke base64
string
semudah:Simpan hasil string base64 dalam kode sumber Anda, misalnya sebagai
const
.Mendekode itu hanya satu panggilan fungsi:
Menyimpan seperti dikutip
string
Lebih efisien daripada menyimpan sebagai base64, tetapi mungkin lebih lama dalam kode sumber adalah menyimpan literal string yang dikutip dari data biner. Kita bisa mendapatkan bentuk kutipan dari string apa pun menggunakan
strconv.Quote()
fungsi:Untuk data biner yang berisi nilai-nilai dari 0 hingga 64, seperti inilah keluarannya (coba di Go Playground ):
"\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:;<=>?"
(Perhatikan bahwa
strconv.Quote()
menambahkan dan menambahkan tanda kutip padanya.)Anda dapat langsung menggunakan string yang dikutip ini di kode sumber Anda, misalnya:
Ini siap digunakan, tidak perlu memecahkan kodenya; penghapusan kutipan dilakukan oleh kompilator Go, pada waktu kompilasi.
Anda juga dapat menyimpannya sebagai potongan byte jika Anda membutuhkannya seperti itu:
sumber
sh
file ke file yang dapat dieksekusi?juga ada beberapa cara eksotis - saya menggunakan plugin maven untuk membangun proyek GoLang dan memungkinkan untuk menggunakan preprocessor JCP untuk menanamkan blok biner dan file teks ke dalam sumber. Dalam kode kasus hanya terlihat seperti baris di bawah ini ( dan beberapa contoh dapat ditemukan di sini )
sumber
sh
atau dapat dieksekusi seperti di atassh
file? Tidak yakin apa yang kamu maksud. Jika Anda ingin semua yang ada di direktori disematkan, ini adalah sesuatu yang telah saya lakukango-bindata
. Misalnya, jika saya memasukkan//go:generate $GOPATH/bin/go-bindata -prefix=data/ -pkg=$GOPACKAGE data/
file go (tidak dihasilkan),go generate ./...
akan menjalankan go-bindata di dir paket, menyematkan semuanya di subdir data tetapi dengan awalan 'data /' dihapus.Sebagai alternatif populer untuk
go-bindata
disebutkan dalam jawaban lain, mjibson / esc juga menyematkan file arbitrer, tetapi menangani pohon direktori dengan nyaman.sumber