Trong ví dụ của bạn, sliceđối số của Testhàm nhận một bản sao của biến atrong phạm vi của người gọi.
Vì một biến lát cắt chứa một "bộ mô tả lát cắt" chỉ tham chiếu đến một mảng bên dưới, trong Testhàm của bạn, bạn sửa đổi bộ mô tả lát cắt được giữ trong slicebiến vài lần liên tiếp, nhưng điều này không ảnh hưởng đến trình gọi và abiến của nó .
Bên trong Testhàm, hàm đầu tiên appendphân bổ lại mảng hỗ trợ bên dưới slicebiến, sao chép nội dung ban đầu của nó lên, gắn 100vào nó và đó là những gì bạn đang quan sát. Khi thoát khỏi Test, slicebiến sẽ vượt ra khỏi phạm vi và mảng cơ bản (mới) cắt các tham chiếu đó cũng vậy. ( Jeff Lee đã đúng về việc đó không phải là những gì thực sự xảy ra, vì vậy phiên bản cập nhật sẽ theo sau; như anh ấy nói một cách chính xác, câu trả lời này là đúng, nếu có thể hơi ngắn gọn.)
Bên ngoài Testhàm, một lát có độ dài 7 và dung lượng 8 được phân bổ, và 7 phần tử của nó được lấp đầy.
Bên trong Testhàm, đầu tiên appendthấy rằng dung lượng của lát cắt vẫn lớn hơn một phần tử so với chiều dài của nó - nói cách khác, có chỗ cho một phần tử nữa để thêm vào mà không cần phân bổ lại. Vì vậy, nó "ăn" phần tử còn lại đó và đặt 100vào đó, sau đó nó điều chỉnh độ dài trong bản sao của bộ mô tả lát cắt để trở nên bằng với giới hạn của lát cắt. Điều này không ảnh hưởng đến bộ mô tả lát cắt trong phạm vi của trình gọi.
Và đó là những gì bạn đang quan sát. Khi thoát khỏi Test, slicebiến sẽ vượt ra khỏi phạm vi và mảng cơ bản (mới) cắt các tham chiếu đó cũng vậy.
Nếu bạn muốn thực hiện Testhành vi như thế nào append, bạn phải trả lại lát mới từ nó - giống như appendhiện tại - và yêu cầu người gọi Testsử dụng nó theo cách họ sẽ sử dụng append:
func Test(slice []int) []int {
slice = append(slice, 100)
fmt.Println(slice)
return slice
}
a = Test(a)
Vui lòng đọc kỹ bài viết này vì về cơ bản nó chỉ cho bạn cách triển khai appendbằng tay, sau khi giải thích cách các lát cắt hoạt động nội bộ. Sau đó, đọc này .