Giới Thiệu
Trong bài viết này, mình sẽ cùng bạn khám phá và tìm hiểu mọi khía cạnh liên quan đến Slices trong Golang, một cấu trúc dữ liệu rất phổ biến. Slices có thể được coi là một phiên bản động hơn của arrays trong các ngôn ngữ lập trình khác. Hãy cùng mình đi sâu vào từng phần với những ví dụ cụ thể để hiểu rõ hơn nhé!
Nội Dung Chi Tiết
Giới Thiệu về Array trong Golang
Trước khi đi vào Slices, mình xin giới thiệu sơ lược về Array trong Golang. Khác với nhiều ngôn ngữ lập trình khác, Array trong Golang có kích thước cố định (fixed size). Điều này có nghĩa là bộ nhớ được cấp phát cho biến Array khi khởi tạo là không thay đổi. Khi bạn gán Array cho một biến khác hoặc truyền vào một hàm, toàn bộ Array sẽ được sao chép thay vì truyền một con trỏ đến phần tử đầu tiên.
Hãy cùng xem một ví dụ đơn giản:
go
package main
import "fmt"
func main() {
a := [5]int{1, 2, 3, 4, 5} // Khởi tạo một biến Array cần chỉ định kích thước
b := a
b[2] = 10
fmt.Println(a) // Kết quả: [1 2 3 4 5]
fmt.Println(b) // Kết quả: [1 2 10 4 5]
}
Như bạn thấy, khi thực hiện thay đổi trên biến b
, biến a
không bị ảnh hưởng bởi chúng là hai bản sao độc lập.
Tìm Hiểu Về Slices trong Golang
Để khắc phục những hạn chế của Array, Golang cung cấp Slices - một giải pháp linh hoạt hơn. Slices tương tự như một Dynamic Array trong các ngôn ngữ khác và thực chất nó là một con trỏ tới phần tử đầu tiên của Slice.
Ví dụ khởi tạo một Slice:
go
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5} // Khởi tạo một Slice mà không cần chỉ định kích thước
fmt.Printf("%p\n", a)
fmt.Printf("%p", &a[0])
}
Khởi Tạo Slices với Hàm make
Một cách khác để khởi tạo Slices là sử dụng hàm make
. Bạn cần chỉ định kiểu dữ liệu, len
(độ dài hiện tại) và cap
(công suất bộ nhớ được cấp phát).
Hãy cùng xem một ví dụ rõ hơn:
go
package main
import "fmt"
func main() {
a := make([]int, 1, 3) // Tạo một Slice có len là 1 và cap là 3
fmt.Println(len(a)) // Kết quả: 1
fmt.Println(cap(a)) // Kết quả: 3
a[0] = 10 // Có thể sử dụng a[0] vì len = 1.
// Không thể sử dụng a[1], a[2] vì sẽ xảy ra lỗi index out of range
a = append(a, 10) // Thêm một phần tử vào Slice.
fmt.Println(len(a)) // Kết quả: 2
fmt.Println(cap(a)) // Kết quả: 3
a = append(a, 1, 2) // Thêm nhiều phần tử hơn cap hiện tại
fmt.Println(len(a)) // Kết quả: 4
fmt.Println(cap(a)) // Kết quả: 6 (thông thường là gấp đôi)
}
Khi bạn sử dụng append
vượt quá cap
, Golang sẽ tự động tìm một vùng nhớ có cap
gấp đôi và sao chép các phần tử hiện tại qua.
Slices được khởi tạo từ Array cũng có thể thay đổi giá trị của Array, do đó bạn có thể biến đổi giá trị của một biến Array thông qua Slices.
Tóm Tắt
Hy vọng rằng bài viết này đã giúp bạn có cái nhìn sâu sắc hơn về cách sử dụng Array và Slices trong Golang. Hãy tự tin sử dụng cấu trúc dữ liệu này để cải thiện hiệu suất và tính linh hoạt trong ứng dụng của bạn.
source: viblo