Go – Slice

Go Slice là một abstraction ở trên mảng Go. Mảng của Go cho phép chúng ta định nghĩa các biến có thể nắm giữ một số các phần tử cùng kiểu dữ liệu nhưng không cung cấp bất kỳ phương thức nào giúp tăng kích thước của nó một cách linh hoạt hoặc lấy một mảng con mà nó sở hữu. Slice loại bỏ giới hạn này. Nó cung cấp nhiều hàm tiện ích cần thiết trên mảng và được sử dụng rộng rãi trong Go.

Cũng giống như mảng, Slice được đánh index và có độ dài. Nhưng không giống như mảng, kích thước của nó có thể thay đổi.

Khai báo Slice

Slice kiểu T được khai báo sử dụng []T giống như khai báo một mảng nhưng không chỉ định rõ kích thước. Ngoài ra, chúng ta có thể dùng hàm make để tạo một Slice.

Chúng ta có thể tạo một Slice sử dụng literal như sau

Biểu thức ở phía bên phải của câu lệnh bên trên là một literal. Slice literal được khai báo tương tự như một mảng literal, ngoại trừ việc bạn chỉ định kích thước trong dấu ngoặc.

Khi bạn tạo một Slice sử dụng literal, trước tiên nó sẽ tạo một  mảng và sau đó trả về một Slice tham chiếu đến nó.

Hãy cùng xem ví dụ sau

Kết quả

Tạo Slice từ một mảng

Vì Slice là một phân đoạn của mảng, nên chúng ta có thể tạo Slice từ mảng.

Để tạo một Slice từ một mảng a, chúng ta chỉ định 2 chỉ số lowhigh phân biệt bằng dấu hai chấm.// tạo slice từ mảng a a[low:high]

Biểu thức trên lựa chon một Slice từ mảng a. Kết quả Slice bao gồm tất cả các phần tử bắt đầu từ index low đến high, nhưng không bao gồm phần tử ở index high

Hãy cũng xem ví dụ sau đây để hiểu rõ hơn

Kết quả

Chỉ số lowhigh trong biểu thức Slice là không bắt buộc. Mặc định giá trị của low là 0, và high là độ dài của Slice.

Kết quả

Tạo Slice từ Slice khác

Slice cũng có thể được tạo từ Slice đang tồn tại.

Kết quả

Sửa đổi một Slice

Slice là kiểu tham chiếu. Chúng tham chiếu đến một mảng cơ sở. Chỉnh sửa các phần tử trong Slice tức là thay đổi các phần tử tương ứng tham chiếu đến mảng. Các Slice khác cùng tham chiếu đến mảng này sẽ thay đổi theo

Kết quả

Độ dài và dung lượng của Slice

Một Slice bao gồm 3 thứ sau:

  • Con trỏ (Ptr) tham chiếu đến một mảng cơ sở
  • Độ dài (len) phân đoạn của mảng mà slice chứa
  • Dung lượng (cap) (Kích thước tối đa mà phân đoạn có thể tăng)

Hãy cùng xem mảng và Slice sau đây thu được

Chúng ta có thể miêu tả Slice s như sau

Độ dài của Slice là số phần tử trong Slice, là 3 ở ví dụ trên

Dung lượng là số phần tử trong mảng cơ sở bắt đầu từ phần tử đầu tiên trong Slice. Nó là 5 ở ví dụ trên.

Bạn có thể tìm độ dài và dung lượng của Slice bằng cách sử dụng hàm len()cap().

Kết quả

Độ dài của Slice có thể tăng bằng dung lượng của nó bằng cách cắt lại nó. Nếu chúng ta thử tăng độ dài của Slice lớn hơn dung lượng thì một lỗi được đưa ra khi chạy.

Hãy cùng xem ví dụ sau đây để hiểu cách chúng ta thay đổi độ dài của Slice và dung lượng

Kết quả

Tạo Slice sử dụng hàm make()

Go cung cấp hàm thư viện được gọi là make() dùng để tạo Slice

Hàm make() nhận giá trị đầu vào là kiểu – []T, độ dài – len, dung lượng – cap (không bắt buộc). Nó cấp phát một mảng cơ sở với kích thước bằng với tham số dung lượng – cap truyền vào, và trả về một Slice tham chiếu đến mảng.

Kết quả

Tham số dung lượng – cap trong hàm make() là không bắt buộc. Khi bị bỏ qua, mặc định của nó xác định theo độ dài

Kết quả

Giá trị 0 của Slice

Giá trị 0 của Slice là nil. Một nil Slice không có bất kỳ mảng cơ sở nào, và có độ dài và dung lượng bằng 0.

Kết quả

Các hàm Slice

Hàm copy(): Sao chép một Slice

Hàm copy() sao chép tất cả phần tử của một Slice sang Slice khác.

Nó nhận vào 2 tham số: dst – Slice đích, src – Slice gốc. Sao chép tất cả các phần tử của gốc sang Slice đích và trả về số phần tử đã được sao chép.

Số phần tử được sao chép sẽ bằng độ dài của Slice nhỏ hơn của Slice gốc – len(src) và Slice đích – len(dst)

Kết quả

Hàm append(): Nối vào một slice

Hàm append() dùng để nối thêm các phần tử mới vào đuôi của Slice cho trước.

Nó nhận vào một Slice và một số lượng các đối số x ...T. Sau đó trả về một Slice mới chứa tất cả các phần tử của Slice cho trước cũng như các phần tử mới.

Nếu Slice cho trước không có đủ dung lượng để chứa các phần tử mới thì một mảng cơ sở mới sẽ được cấp phát với dung lượng lớn hơn. Tất cả các phần tử từ mảng cơ sở của Slice hiên tại được sao chép sang mảng mới này, sau đó các phần tử mới được nối thêm vào.

Tuy nhiên, nếu Slice có đủ dung lượng để chứa các phần tử mới, thì hàm append() sử dụng lại mảng cơ sở và thêm các phần tử mới vào chính mảng hiện tại.

Kết quả

Trong ví dụ trên, slice1 có dung lượng là 3, nó không thể chứa thêm phần tử. Nên mảng cơ sở mới được cấp phát với dung lượng lớn hơn khi chúng ta thêm phần tử mới cho nó.

Nếu chúng ta thay đổi slice1slice2 sẽ không thấy những thay đổi ảnh hưởng đến nhau bởi vì chúng đang được tham chiếu đến 2 mảng khác nhau.

Nhưng chuyện gì xảy ra nếu slice1 có đủ dung lượng để chứa các phần tử mới? Trong trường hợp này, sẽ không có mảng mới nào được cấp phát, và các phần tử được thêm vào mảng cơ sở hiện tại. Do đó, trong trường hợp này, những thay đổi trong slice1 sẽ ảnh hưởng đến slice2.

Kết quả

Nối vào một Slice nil

Khi bạn thêm vào các giá trị cho một Slice nil, nó cấp phát một Slice mới và trả về tham chiếu đến một Slice mới.

Kết quả

Nối Slice với Slice khác

Bạn có thể nối một Slice với một Slice khác sử dụng toán tử .... Toán tử này giúp mở rộng Slice thành một danh sách các đối số.

Kết quả

Slice của Slice

Slice có thể là kiểu dữ liệu bất kỳ. Nên chúng ta có thể chứa các Slice khác.

Kết quả

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

avatar
  Subscribe  
Notify of