Bài 1: Tổng quan về net/http trong Go
Package net/http là thư viện tiêu chuẩn (standard library) cốt lõi của Go, cung cấp các tính năng mạnh mẽ để xây dựng cả HTTP Client (gọi API) và HTTP Server (cung cấp API). Điểm đặc biệt của Go là thư viện tiêu chuẩn này đủ mạnh và tối ưu để chạy trực tiếp trên môi trường production mà không nhất thiết phải dựa vào các web framework bên thứ ba.
1. Các thành phần cốt lõi
Kiến trúc của net/http xoay quanh 4 đối tượng (types) chính mà bạn sẽ tương tác liên tục:
-
http.Request: Cấu trúc (struct) chứa mọi thông tin của một yêu cầu HTTP gửi đến (URL, Headers, Body, Method). Nó được dùng cả ở phía Client (tạo request để gửi đi) và phía Server (nhận request từ client). -
http.ResponseWriter: Một interface cung cấp các phương thức để cấu hình và gửi phản hồi (HTTP response) từ Server trở lại cho Client (như ghi Status Code, Headers, và Body). -
http.Server: Đại diện cho HTTP server, chịu trách nhiệm lắng nghe các kết nối TCP/IP, đọc request và chuyển giao cho các handler xử lý. -
http.Client: Đại diện cho một HTTP client dùng để quản lý cấu hình khi gửi request ra bên ngoài (quản lý connection pool, timeouts, cookies).
2. Sức mạnh đồng thời (Concurrency)
Khác với NodeJS (chạy single-thread event loop) hay PHP (thường dùng process/thread pool của PHP-FPM), net/http của Go tự động xử lý mỗi request đến trên một Goroutine riêng biệt.
Cơ chế này mang lại các lợi thế cực lớn:
-
Mã nguồn (handler) được viết theo luồng đồng bộ (synchronous) từ trên xuống dưới, cực kỳ dễ đọc và debug.
-
Một request thực hiện thao tác I/O nặng (query database lâu, gọi API ngoài) sẽ bị block (chặn) trên goroutine của chính nó, hoàn toàn không làm ảnh hưởng đến hàng ngàn request khác đang được server xử lý đồng thời.
-
Tận dụng tối đa sức mạnh của CPU đa nhân một cách tự nhiên.
3. Trải nghiệm nhanh với net/http
Để hiểu cách package này hoạt động, hãy xem hai kịch bản cơ bản nhất:
Xây dựng HTTP Server:
Go
package main
import (
"fmt"
"net/http"
)
func main() {
// Đăng ký một route "/" và logic xử lý (handler)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// w: dùng để trả dữ liệu về client
// r: chứa thông tin client gửi lên
fmt.Fprintf(w, "Xin chào, đây là server Go!")
})
// Khởi động server lắng nghe tại port 8080
http.ListenAndServe(":8080", nil)
}
Tạo một HTTP Client gọi API:
Go
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
// Gửi một GET request nhanh
resp, err := http.Get("https://api.github.com")
if err != nil {
panic(err)
}
// QUAN TRỌNG: Phải luôn đóng Body sau khi đọc xong để giải phóng kết nối TCP
defer resp.Body.Close()
// Đọc toàn bộ nội dung phản hồi
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
4. Khi nào nên dùng Framework ngoài?
Dù hệ sinh thái Go có nhiều framework nổi tiếng như Gin, Echo, hay Fiber, bản thân chúng phần lớn đều được bọc (wrapper) bên ngoài cấu trúc cốt lõi của net/http.
-
Chỉ dùng
net/http: Phù hợp khi xây dựng các microservice nhỏ, hệ thống cần ít dependencies để dễ bảo trì, hoặc từ bản Go 1.22 trở lên (khi Go đã cập nhật hệ thống routing mặc định hỗ trợ path parameters và HTTP methods rất tốt). -
Dùng Framework: Phù hợp khi bạn cần tốc độ phát triển nhanh nhờ các tính năng bọc sẵn (auto-bind JSON vào struct, data validation, auto-generate Swagger, hay quản lý middleware phức tạp).
Việc nắm vững net/http là bắt buộc, vì dù sau này bạn dùng framework nào, bạn cũng sẽ thao tác với các nguyên lý cốt lõi của package này.
All rights reserved