Khắc phục lỗi Go Panic: runtime error: index out of range [X] with length Y

người mới bắt đầu🔷 Go2026-04-01| Mọi môi trường Go (Linux, macOS, Windows), Go 1.x+

Error Message

panic: runtime error: index out of range [X] with length Y
#go#panic#gỡ lỗi#slices#xử lý lỗi

Kịch bản gây lỗiHãy tưởng tượng: bạn đang thử nghiệm một tính năng mới, bạn nhấn chạy, và terminal của bạn đột nhiên bùng nổ với một stack trace đáng sợ. Ngay trên cùng, bạn thấy thông báo lỗi quen thuộc:

panic: runtime error: index out of range [3] with length 3

Lỗi này thường xuất hiện khi mã của bạn cố gắng lấy một phần tử từ một slice, mảng (array) hoặc chuỗi (string) không tồn tại. Go sử dụng chỉ số (index) bắt đầu từ 0. Nếu bạn có danh sách 3 người dùng, họ nằm ở các vị trí 0, 1 và 2. Việc cố gắng truy cập chỉ số 3 giống như yêu cầu người thứ tư trong một hàng chỉ có ba người—điều đó là không thể, vì vậy Go sẽ kéo phanh khẩn cấp để bảo vệ bộ nhớ của bạn.

Một sai lầm kinh điển: Đối số dòng lệnhHãy xem lỗi phổ biến này, nơi lập trình viên giả định rằng người dùng sẽ luôn cung cấp đầu vào:

package main

import (
	"fmt"
	"os"
)

func main() {
	// Chúng ta đang lấy đối số đầu tiên do người dùng cung cấp
	arg := os.Args[1]
	fmt.Println("Đối số được cung cấp:", arg)
}

Nếu bạn chạy go run main.go mà không truyền thêm bất kỳ từ nào, os.Args chỉ chứa một thứ: chính tên chương trình ở chỉ số 0. Vì chỉ số 1 để trống, chương trình sẽ bị sập ngay lập tức với lỗi index out of range [1] with length 1.

Giải mã lỗi PanicThông báo lỗi cung cấp cho bạn tọa độ chính xác của sự cố:

  • [X]: Chỉ số cụ thể mà mã của bạn đã cố gắng truy cập.- length Y: Số lượng phần tử thực tế có trong tập hợp.Phép toán rất đơn giản: chỉ số của bạn phải nhỏ hơn độ dài. Trong khi các ngôn ngữ như Python có thể ném ra IndexError hoặc JavaScript có thể chỉ trả về undefined, Go nghiêm ngặt hơn nhiều. Nó dừng thực thi để ngăn chặn các hành vi không lường trước hoặc hỏng bộ nhớ.

Cách khắc phục nhanh: Bảo vệ quyền truy cậpCách nhanh nhất để ngăn chặn lỗi này là kiểm tra độ dài đơn giản. Đừng bao giờ chạm vào một chỉ số trừ khi bạn đã xác nhận rằng nó tồn tại.

package main

import (
	"fmt"
	"os"
)

func main() {
	// Kiểm tra xem người dùng có thực sự cung cấp đối số hay không
	if len(os.Args) > 1 {
		arg := os.Args[1]
		fmt.Println("Đối số được cung cấp:", arg)
	} else {
		fmt.Println("Lỗi: Bạn đã quên cung cấp đối số!")
	}
}

Bằng cách thêm len(os.Args) > 1, bạn đã xây dựng một rào chắn an toàn. Mã bên trong khối if chỉ chạy khi đảm bảo an toàn.

Các chiến lược tốt hơn để mã nguồn linh hoạt hơnKiểm tra thủ công là giải pháp ổn cho các trường hợp đơn lẻ, nhưng chúng có thể làm mã của bạn trở nên lộn xộn nếu bị lạm dụng quá mức. Dưới đây là cách xử lý dữ liệu chuẩn Go hơn.

1. Hãy để 'for range' đảm nhận công việc nặng nhọcTránh sử dụng các biến chỉ số thủ công bất cứ khi nào có thể. Từ khóa range là tiêu chuẩn vàng để lặp trong Go vì về mặt vật lý, nó không thể vượt quá phạm vi.

Cách làm rủi ro:

items := []string{"táo", "chuối", "anh đào"}
for i := 0; i <= len(items); i++ { // Sử dụng '<=' là một lỗi off-by-one sắp xảy ra
	fmt.Println(items[i])
}

Cách chuẩn Go:

items := []string{"táo", "chuối", "anh đào"}
for _, item := range items {
	fmt.Println(item)
}

2. Cắt Slice an toàn hơnKhi bạn lấy một slice con, ví dụ data[0:10], Go sẽ panic nếu dữ liệu gốc có ít hơn 10 phần tử. Nếu bạn đang xử lý dữ liệu động—như tệp CSV 500 dòng trong đó một số dòng có thể ngắn—hãy luôn giới hạn chỉ số của bạn.

func getPreview(data []int, limit int) []int {
	if limit > len(data) {
		limit = len(data)
	}
	return data[0:limit]
}

3. Khởi đầu phòng thủHãy giả định rằng các slice của bạn có thể trống. Nếu hàm của bạn phụ thuộc vào data[0], hãy kiểm tra độ dài ngay đầu hàm và trả về sớm (return early) nếu không có gì để xử lý.

Cách xác minh bản sửa lỗiĐừng chỉ giả định rằng nó đã được sửa. Hãy kiểm tra mã của bạn qua các bước sau:

  • Kiểm tra các trường hợp biên: Nếu mã của bạn xử lý một danh sách, chuyện gì sẽ xảy ra nếu danh sách đó trống? Nếu nó chỉ có đúng một phần tử thì sao?- Unit Testing: Viết một trường hợp kiểm thử truyền một slice nil hoặc trống vào hàm của bạn để đảm bảo nó xử lý khoảng trống đó một cách khéo léo.- Sử dụng phân tích tĩnh: Chạy go vet ./.... Nó sẽ không bắt được mọi lỗi runtime, nhưng rất giỏi trong việc phát hiện các lỗi "off-by-one" rõ ràng trong các vòng lặp của bạn.Việc chuyển từ lập chỉ số thủ công sang vòng lặp range và các câu lệnh bảo vệ (guard clauses) sẽ biến các tập lệnh mong manh thành phần mềm sẵn sàng cho môi trường production.

Related Error Notes