Go'da, kaynakların bir CDN veya Nginx gibi HTTP sunucusu aracılığıyla ayrı ayrı sunulacağı normal bir web uygulamasının tam tersi olan küçük, bağımsız bir web uygulaması oluşturmak istedim.
Bununla birlikte, performans kritik bir sorun değilse veya uygulama düşük trafiğe yönelikse, bağımsız bir uygulamanın kullanılması, yalnızca yürütülebilir bir ikili dosya olduğundan dağıtım ve dağıtımı basitleştirir.
Kaynakları bir Go uygulamasına gömmek için çeşitli paketler mevcuttur:
Her kütüphanenin ayrıntılarına girmeyeceğim ama kullanım kolaylığı ve aktif desteği nedeniyle bindata yaklaşımını tercih ediyorum.
Öncelikle projenizdeki frontend/
dizini içinde bir index.html
oluşturalım:
<html> <body> Hello, World! </body> </html>
Artık bir proje kurulumumuz ve test edilecek statik bir kaynağımız olduğuna göre, şu komutu kullanarak bindata'yı yükleyelim:
go get -u github.com/jteeuwen/go-bindata/...
Web uygulamasının arka uç kodunu çalıştırmaya hazırız. Bir main.go
dosyası oluşturun ve aşağıdaki kodu kopyalayın:
package main import ( "bytes" "io" "net/http" ) //go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/... func static_handler(rw http.ResponseWriter, req *http.Request) { var path string = req.URL.Path if path == "" { path = "index.html" } if bs, err := Asset(path); err != nil { rw.WriteHeader(http.StatusNotFound) } else { var reader = bytes.NewBuffer(bs) io.Copy(rw, reader) } } func main() { http.Handle("/", http.StripPrefix("/", http.HandlerFunc(static_handler))) http.ListenAndServe(":3000", nil) }
Bu koddaki önemli satır:
//go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/...
Yukarıdaki satır, go generate
çağrıldığında go-bindata
komutunu çalıştırmamızı sağlar. Sürüm 1.4'ten itibaren, oluşturma aşamasında özel komutları çalıştırabilirsiniz. Bu sadece go dosyanıza //go:generate command argument...
eklemek meselesidir.
go-bindata
komut satırının çeşitli parametreleri vardır, bu nedenle nasıl kullanılacağına ilişkin belgelere bakın. Bizim durumumuzda şöyle diyoruz:
-prefix "frontend/"
statik için yol adının bir kısmını tanımlar
-pkg main
oluşturulan kodda kullanılan paket adını tanımlar
-o bindata.go
oluşturulan dosyanın adını tanımlayın
go generate
komutunu çalıştırdıktan sonra bindata.go
adında oluşturulmuş bir dosya görmelisiniz. Projenizin yapısı şu şekilde görünmelidir:
. │ ├── bindata.go (auto-generated file) ├── frontend │ └── index.html └── main.go
Statik dosyaları sunma mantığı, isteği alan ve yolun statik yolla eşleşip eşleşmediğini kontrol eden static_handler
işlevindedir. Kontrol, bindata.go
kullanıcısı tarafından otomatik olarak dışa aktarılan Asset
işlevi kullanılarak yapılır. Kaynak mevcut değilse 404
değerini döndürürüz, aksi halde kaynağın içeriğini döndürürüz.
Kodun geri kalanı web uygulamasını oluşturmak ve static_handler
şablonumuzu /
için gelen tüm isteklerle eşleşecek şekilde bağlamak içindir. Bu kodu anlamada sorun yaşıyorsanız http package
için resmi Go belgelerine bakın.
Go'nun paketleri nasıl yönettiğine dair kısa bir hatırlatma olarak, tanımlayıcı adının ilk harfi büyük harfle başlıyorsa, tüm tanımlayıcılar aynı ada sahip diğer paketlere otomatik olarak aktarılacaktır.
Bu kurala dayanarak bindata.go
dosyası main
paket için Asset
işlevini sağlar. Bu, verilen ad için bir varlık yükler ve döndürür. Kaynak bulunamazsa veya yüklenemezse hata döndürür.