Trong ví dụ của bạn, slice
đối số của Test
hàm nhận một bản sao của biến a
trong 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 Test
hàm của bạn, bạn sửa đổi bộ mô tả lát cắt được giữ trong slice
biế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à a
biến của nó .
Bên trong Test
hàm, hàm đầu tiên append
phân bổ lại mảng hỗ trợ bên dưới slice
biến, sao chép nội dung ban đầu của nó lên, gắn 100
vào nó và đó là những gì bạn đang quan sát. Khi thoát khỏi Test
, slice
biế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 Test
hà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 Test
hàm, đầu tiên append
thấ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 100
và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
, slice
biế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 Test
hành vi như thế nào append
, bạn phải trả lại lát mới từ nó - giống như append
hiện tại - và yêu cầu người gọi Test
sử 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 append
bằ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 .