# Ứng dụng Go

> Cài bộ công cụ Go, deploy dịch vụ Go từ Git với lệnh build và chạy tự động, lắng nghe trên PORT, đặt biến môi trường và xử lý lỗi thường gặp.

Source: https://zopanel.net/vi/docs/go  
Updated: 2026-10-09

Ứng dụng Go chạy trên ZoPanel như một ứng dụng server: ZoPanel biên dịch từ mã nguồn bằng bộ công cụ Go chính thức, chạy file thực thi như một dịch vụ của tài khoản hosting phía sau nginx và phát hành bản mới không gián đoạn. Trang này dành cho dịch vụ HTTP và API viết bằng Go; cơ chế chung (cổng, phát hành blue/green, log) được mô tả trong [Ứng dụng Node.js và Python](/vi/docs/apps-node-python).

## Cài Go lên máy chủ

Quản trị viên cài Go một lần:

1. Mở **Runtime**.
2. Trong thẻ **Go** ("Bộ công cụ Go chính thức."), bấm **Cài bản mới nhất**.

ZoPanel tải bản ổn định mới nhất cho kiến trúc của máy chủ (amd64 hoặc arm64) từ `go.dev`, kiểm tra checksum SHA-256 và cài vào `/opt/zopanel/runtimes/go/<major.minor>`, ví dụ `1.25`. Cài lại về sau sẽ thêm phiên bản minor mới bên cạnh bản cũ. Gỡ một phiên bản bằng biểu tượng thùng rác trên nhãn của nó.

**Chọn phiên bản:** mỗi lần deploy dùng phiên bản đã cài khớp với dòng `go` trong `go.mod` (`go 1.24` → `1.24`), nếu không có thì dùng bản mới nhất đã cài. Khi `go.mod` yêu cầu Go mới hơn bản đang dùng, Go 1.21 trở lên tự tải toolchain cần thiết trong lúc build ([Go toolchains](https://go.dev/doc/toolchain)); cài bản mới nhất sẽ tránh được bước tải này.

## Chuẩn bị ứng dụng

Chương trình phải lắng nghe tại `127.0.0.1` trên cổng trong biến môi trường `PORT`. ZoPanel đặt `PORT` (và `HOST=127.0.0.1`) cho mỗi bản release; slot blue/green thứ hai dùng cổng khác, vì vậy đừng bao giờ ghi cứng cổng.

```go
package main

import (
	"net/http"
	"os"
)

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello from Go"))
	})
	http.ListenAndServe("127.0.0.1:"+os.Getenv("PORT"), mux)
}
```

nginx xử lý SSL và chuyển mọi request tới ứng dụng kèm các header `Host`, `X-Real-IP`, `X-Forwarded-For` và `X-Forwarded-Proto`. Hãy lấy địa chỉ khách từ `X-Forwarded-For` hoặc `X-Real-IP`, không lấy từ `r.RemoteAddr` vì giá trị này luôn là `127.0.0.1`.

## Deploy

1. Ở **Website → Thêm website**, chọn **Git deploy**, nhập **Địa chỉ repository**, **Nhánh** (và **Thư mục gốc** nếu `go.mod` nằm trong thư mục con) rồi bấm **Tạo website**. Với website có sẵn, dùng tab **Deploy**.
2. ZoPanel nhận diện Go qua file `go.mod` và build bản release đầu tiên.
3. Khai báo cấu hình trong **Biến môi trường** rồi bấm **Lưu & deploy lại**.

Bạn cũng có thể tải mã nguồn lên `domains/<tên-miền>/source` và chọn **Nguồn** là **File đã tải lên (Quản lý file)** (xem [Git deploy](/vi/docs/git-deploy)).

### Lệnh build và chạy được nhận diện

| Cấu trúc repository | Lệnh build | Lệnh chạy |
| --- | --- | --- |
| `main.go` ở thư mục gốc | `CGO_ENABLED=0 go build -o bin/<tên> .` | `./bin/<tên>` |
| `cmd/<lệnh>/main.go` | `mkdir -p bin && CGO_ENABLED=0 go build -o bin/ ./cmd/...` | `./bin/<lệnh đầu tiên theo thứ tự chữ cái>` |
| Không có cả hai | `CGO_ENABLED=0 go build -o bin/<tên> .` | `./bin/<tên>` |

- `<tên>` là phần cuối của đường dẫn `module` trong `go.mod` (`github.com/acme/api` → `api`), hoặc `app`.
- Lệnh cài đặt là `go mod download`.
- Khi có nhiều lệnh trong `cmd/`, log deploy ghi "Multiple commands found in cmd/, starting …". Muốn chạy lệnh khác, tắt **Tự nhận diện** rồi sửa **Lệnh chạy**, ví dụ `./bin/server`.
- `bin/` được thêm vào `PATH` khi ứng dụng khởi động, nên dòng `Procfile` như `web: api` vẫn chạy được. Dòng `web:` trong `Procfile` luôn được dùng làm lệnh chạy.

Muốn đổi lệnh nào, tắt **Tự nhận diện** trong thẻ **Build & chạy**, sửa rồi bấm **Lưu & deploy**. Nối nhiều bước build bằng `&&` trên một dòng, ví dụ `go generate ./... && CGO_ENABLED=0 go build -o bin/api .`.

### Môi trường build

- Build chạy dưới quyền tài khoản hosting, trong giới hạn CPU và RAM của tài khoản, tối đa 30 phút cho lệnh cài đặt và 30 phút cho lệnh build.
- Module cache (`GOPATH`) và build cache (`GOCACHE`) nằm trong thư mục home của tài khoản và được giữ giữa các lần deploy, nên các lần build sau nhanh hơn.
- `CGO_ENABLED=0` tạo file thực thi tĩnh. Package cần cgo (ví dụ `github.com/mattn/go-sqlite3`) phải dùng `CGO_ENABLED=1` và cần trình biên dịch C trên máy chủ; nên chọn bản thuần Go như `modernc.org/sqlite`.

## Biến môi trường

Đặt cấu hình và thông tin bí mật trong **Biến môi trường** ở tab **Deploy**. Các biến dùng được khi build và khi chạy; **Dán .env** thêm nhiều biến một lúc (tối đa 200 biến, giá trị trên một dòng). Thành viên chỉ có quyền xem không thấy được giá trị.

Ví dụ với database MariaDB tạo ở **Cơ sở dữ liệu**:

```dotenv
DATABASE_URL=alice_api:mat-khau@tcp(127.0.0.1:3306)/alice_api?parseTime=true
```

Định dạng chuỗi kết nối tuỳ driver bạn dùng; host là `127.0.0.1` (xem [Cơ sở dữ liệu](/vi/docs/databases)).

File cần giữ lại giữa các bản release, như thư mục upload hay database SQLite, hãy đưa vào **Đường dẫn lưu trữ cố định** (ví dụ `data`). Mọi thứ khác trong thư mục release được thay mới ở mỗi lần deploy.

## Release, log và khởi động lại

- Bản mới khởi động ở slot đang rảnh và phải trả lời **Đường dẫn health check** (mặc định `/`) với mã dưới 500 trong vòng 90 giây. Chỉ khi đó nginx mới chuyển sang bản mới và tiến trình cũ mới dừng. Nếu chương trình thoát hoặc không trả lời, bản đang chạy được giữ nguyên.
- **Các bản release** giữ 5 bản build gần nhất để **Rollback**.
- **Log ứng dụng** trong tab **Deploy** hiển thị 400 dòng cuối chương trình ghi ra stdout và stderr; bật **Trực tiếp** để theo dõi. Hãy ghi log ra stdout thay vì ra file.
- Dịch vụ tự khởi động lại khi tiến trình thoát. Hãy dừng chương trình gọn gàng khi nhận `SIGTERM`: khi phát hành, tiến trình cũ có 20 giây trước khi bị buộc dừng.

RAM, CPU và số tiến trình được tính vào gói của tài khoản (xem [Gói và giới hạn](/vi/docs/packages-limits)).

## Xử lý sự cố

| Thông báo hoặc hiện tượng | Cách xử lý |
| --- | --- |
| "Go is not installed — install it under Runtimes" | Nhờ quản trị viên bấm **Cài bản mới nhất** trong thẻ **Go**. |
| "the app did not respond on port … within 90s (it must listen on $PORT)" | Lắng nghe tại `127.0.0.1:$PORT`. Cổng cố định như `:8080` sẽ không bao giờ nhận được request. |
| "the app exited during startup" | Đọc **Log ứng dụng**: thường do thiếu biến môi trường hoặc không kết nối được database. |
| `install failed` ở bước `go mod download` | Không tải được module riêng tư. Hãy vendor thư viện (`go mod vendor`), commit `vendor/`, rồi tắt **Tự nhận diện** và xoá **Lệnh cài đặt**: `go build` tự dùng `vendor/`. |
| `go: go.mod requires go >= …` | Cài Go mới nhất ở **Runtime**, hoặc để toolchain tải xong. |
| Build lỗi liên quan cgo | Dùng package thuần Go, hoặc đặt `CGO_ENABLED=1` trong lệnh build nếu máy chủ có trình biên dịch C. |
| Repository bị nhận diện là Node.js | File `package.json` ở thư mục gốc được ưu tiên hơn `go.mod`. Tắt **Tự nhận diện**, chọn **Runtime** là `go`, **Loại** là **Ứng dụng server (tiến trình)** và tự nhập các lệnh. |
| 502 Bad Gateway | Tiến trình không lắng nghe. Xem **Log ứng dụng** và **Chạy chẩn đoán** ở tab **Nhật ký**. |

## Xem thêm

- [Ứng dụng Node.js và Python](/vi/docs/apps-node-python)
- [Git deploy](/vi/docs/git-deploy)
- [Cơ sở dữ liệu](/vi/docs/databases)
- [Gói và giới hạn](/vi/docs/packages-limits)
- [Tài liệu Go](https://go.dev/doc/)
