Giải mã lỗiBạn chạy lệnh go run main.go và thay vì ứng dụng hoạt động, bạn nhận được một loạt thông báo kết thúc bằng connection refused. Thật khó chịu, nhưng thông báo này thực chất khá cụ thể. Gói net của Go đưa ra lỗi này khi mã nguồn của bạn tìm thấy IP mục tiêu (như 127.0.0.1) thành công, nhưng hệ điều hành tại đích đến đó đã chủ động từ chối yêu cầu trên cổng bạn đã chọn (như 5432).
Hãy tưởng tượng việc này giống như gọi đến một số điện thoại đúng, nhưng người ở đầu dây bên kia dập máy ngay lập tức vì họ không nhận cuộc gọi trên đường dây cụ thể đó.
Tại sao kết nối thất bạiHầu hết các lập trình viên gặp phải lỗi này vì một trong bốn lý do sau:
- Dịch vụ không hoạt động: Cơ sở dữ liệu của bạn (PostgreSQL, Redis, v.v.) thực tế chưa được chạy.- Sai cổng (port): Bạn đang cố kết nối với cổng 5432, nhưng dịch vụ thực tế đang lắng nghe trên cổng 5433 hoặc 8080.- Bị cô lập: Dịch vụ đang chạy nhưng chỉ lắng nghe các lưu lượng truy cập nội bộ (local), trong khi bạn đang cố gắng truy cập nó từ một giao diện mạng khác.- Bẫy Docker: Ứng dụng Go của bạn nằm trong một container và nó coi
localhostlà chính nó, thay vì là máy tính của bạn.## Các bước khắc phục cụ thể### 1. Kiểm tra trạng thái dịch vụĐầu tiên, hãy đảm bảo dịch vụ mục tiêu thực sự đang hoạt động. Nếu bạn đang sử dụng PostgreSQL trên cổng 5432, hãy kiểm tra trạng thái của nó ngay lập tức. Một dịch vụ bị sập hoặc chưa bao giờ khởi động là nguyên nhân phổ biến nhất.
# Trên Linux (systemd) systemctl status postgresql # Trên macOS (Homebrew) brew services list
Nếu trạng thái là inactive hoặc stopped, hãy khởi động nó. Nếu nó chưa được cài đặt, đó chính là trở ngại đầu tiên của bạn.
2. Kiểm tra Cổng và Địa chỉChuỗi kết nối Go của bạn có thực sự khớp với thực tế không? Một nỗ lực kết nối TCP tiêu chuẩn trong Go sẽ trông như thế này:
// Thử thực hiện bắt tay TCP conn, err := net.Dial("tcp", "127.0.0.1:5432") if err != nil { log.Fatalf("Kết nối thất bại: %v", err) }
Kiểm tra xem có dịch vụ nào thực sự đang lắng nghe trên cổng đó hay không bằng cách sử dụng lsof. Nếu kết quả trống, không có dịch vụ nào đang chiếm giữ cổng đó.
# Tìm các dịch vụ lắng nghe trên cổng 5432 sudo lsof -i :5432 # Hoặc sử dụng netstat để kiểm tra nhanh netstat -tuln | grep 5432
3. Giải mã bí ẩn 'Localhost' trong DockerĐây là sai lầm phổ biến nhất trong phát triển phần mềm hiện đại. Khi mã Go của bạn chạy bên trong một Docker container, 127.0.0.1 sẽ trỏ đến loopback nội bộ của container, chứ không phải máy chủ (host) của bạn. Cơ sở dữ liệu của bạn không nằm trong container đó, vì vậy kết nối sẽ thất bại ngay lập tức.
Cập nhật chuỗi kết nối dựa trên hệ điều hành của bạn:
- macOS và Windows: Thay
127.0.0.1bằnghost.docker.internal.- Linux: Sử dụng IP của gateway (thường là172.17.0.1) hoặc chạy container với--network="host"để chia sẻ ngăn xếp mạng của máy chủ.### 4. Kiểm tra địa chỉ ràng buộc (Bind Address)Đôi khi một dịch vụ bị giới hạn. Nó có thể được cấu hình để chỉ lắng nghe trên127.0.0.1, điều đó có nghĩa là nó sẽ bỏ qua mọi yêu cầu đến từ IP bên ngoài hoặc Docker bridge. Hãy xem tệp cấu hìnhpostgresql.confhoặc tệp tương tự:
# postgresql.conf listen_addresses = 'localhost' # Nghiêm ngặt: chỉ các ứng dụng cục bộ mới có thể kết nối listen_addresses = '*' # Mở: cho phép kết nối từ bất kỳ giao diện mạng nào
Sau khi thay đổi thành '*', bạn phải khởi động lại dịch vụ để các thay đổi có hiệu lực.
Xác minh kết quả trong 5 giâyĐừng đợi ứng dụng Go biên dịch xong chỉ để kiểm tra bản sửa lỗi. Hãy sử dụng nc (netcat) để xem cổng có đang mở và chấp nhận lưu lượng hay không:
# Kiểm tra ping nhanh nc -vz 127.0.0.1 5432
Một kết nối thành công sẽ trả về: Connection to 127.0.0.1 port 5432 [tcp/postgresql] succeeded!. Nếu nó vẫn báo bị từ chối (refused), vấn đề nằm ở tường lửa hoặc cấu hình dịch vụ của bạn, không phải ở mã nguồn Go.

