Tôi muốn tạo một ứng dụng web độc lập nhỏ trong Go, đối lập với ứng dụng web thông thường nơi tài nguyên sẽ được cung cấp riêng biệt thông qua máy chủ CDN hoặc HTTP như Nginx.
Tuy nhiên, nếu hiệu suất không phải là mối quan tâm nghiêm trọng hoặc ứng dụng dành cho lưu lượng truy cập thấp thì việc sử dụng một ứng dụng độc lập sẽ đơn giản hóa việc triển khai và phân phối vì đây chỉ là một tệp nhị phân có thể thực thi được.
Một số gói có sẵn để nhúng tài nguyên vào ứng dụng Go:
Tôi sẽ không đi sâu vào chi tiết cụ thể của từng thư viện, nhưng tôi thích cách tiếp cận bindata hơn do tính dễ sử dụng và hỗ trợ tích cực của nó.
Trước tiên, hãy tạo một index.html
bên trong thư mục frontend/
trong dự án của bạn:
<html> <body> Hello, World! </body> </html>
Bây giờ chúng ta đã thiết lập dự án và tài nguyên tĩnh để kiểm tra, hãy cài đặt bindata bằng lệnh:
go get -u github.com/jteeuwen/go-bindata/...
Chúng tôi đã sẵn sàng chạy mã phụ trợ của ứng dụng web. Tạo tệp main.go
và sao chép đoạn mã sau:
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) }
Dòng quan trọng trong mã này:
//go:generate go-bindata -prefix "frontend/" -pkg main -o bindata.go frontend/...
Dòng trên cho phép chúng ta chạy lệnh go-bindata
khi go generate
được gọi. Kể từ phiên bản 1.4, bạn có thể chạy các lệnh tùy chỉnh trong giai đoạn tạo. Đó chỉ là vấn đề thêm //go:generate command argument...
vào tệp go của bạn.
Dòng lệnh go-bindata
có một số tham số, vì vậy hãy kiểm tra tài liệu về cách sử dụng nó. Trong trường hợp của chúng tôi, chúng tôi nói:
-prefix "frontend/"
xác định một phần tên đường dẫn cho tĩnh
-pkg main
xác định tên gói được sử dụng trong mã được tạo
-o bindata.go
xác định tên của tệp được tạo
Sau khi chạy lệnh go generate
, bạn sẽ thấy một tệp được tạo có tên bindata.go
. Cấu trúc dự án của bạn sẽ trông như thế này:
. │ ├── bindata.go (auto-generated file) ├── frontend │ └── index.html └── main.go
Logic để phân phát các tệp tĩnh nằm trong hàm static_handler
, hàm này nhận yêu cầu và kiểm tra xem đường dẫn có khớp với đường dẫn tĩnh hay không. Việc kiểm tra được thực hiện bằng cách sử dụng hàm Asset
, được người dùng bindata.go
tự động xuất. Nếu tài nguyên không tồn tại, chúng tôi sẽ trả về 404
, nếu không, chúng tôi sẽ trả về nội dung của tài nguyên.
Phần còn lại của mã là để tạo ứng dụng web và liên kết mẫu static_handler
của chúng tôi để khớp với tất cả các yêu cầu đến cho /
. Nếu bạn gặp khó khăn trong việc hiểu mã này, hãy xem tài liệu Go chính thức dành cho http package
.
Như một lời nhắc nhở nhanh về cách Go xử lý các gói, tất cả số nhận dạng sẽ được tự động xuất sang các gói khác có cùng tên nếu chữ cái đầu tiên của tên số nhận dạng bắt đầu bằng chữ in hoa.
Dựa trên quy tắc này, tệp bindata.go
cung cấp hàm Asset
cho gói main
. Việc này tải và trả về một nội dung cho tên đã cho. Nó trả về lỗi nếu không tìm thấy tài nguyên hoặc không thể tải được tài nguyên.