[Golang] Go Slices deep dive
Giới thiệu
Trong bài viết này mình sẽ giới thiệu cũng như giải thích tất tần tật về Slice trong Golang, một datas structure được sử dụng phổ biến. Nghĩ đơn giản thì Slices cũng giống như array trong các ngôn ngữ khác. Ở bài viết này mình sẽ đi chi tiết từng phần một cũng như code demo x10 uy tín 😁
Nội dung
Array trong Golang
Đầu tiên thì mình sẽ nói qua về Array trong Golang, không giống như nhiều ngôn ngữ khác Array trong Golang là một fixed size variable, tức là bộ nhớ được cấp phát cho biến Array là cố định. Không giống như C Array sẽ là Pointer vào phần tử đầu tiên. Array trong Golang là biến chứa tất cả phần tử trong Array đó. Mỗi lần gán hay truyền vào một hàm nó sẽ copy Array ra chứ không phải truyền Pointer 🤔 OKE DEMO
package main
import "fmt"
func main() {
a := [5]int{1, 2, 3, 4, 5} // để khởi tạo 1 biến array cần chỉ định size của nó
b := a
b[2] = 10
fmt.Println(a)
fmt.Println(b)
}
// [1 2 3 4 5]
// [1 2 10 4 5]
OKE giờ thì bạn đã rõ hơn rồi Array giống như Int có điều chứ nhiều Int chứ không phải con trỏ vào phần tử đầu tiên ha 😅 Thì như đã nói ở trên Array có 1 số giới hạn như là số phần tử cố định, không flexible cho lắm nên cũng ít được sử dụng
Slices trong Golang
Slices sẽ giúp chúng ta giải quyết bài toán trên. Slice khá giống như Dynamic Array trong nhiều ngôn ngữ khác là biến giữ pointer vào phần tử đầu tiên của Slices.
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5} // để khởi tạo 1 biến Slices không cần chỉ định size của nó
fmt.Printf("%p\n", a)
fmt.Printf("%p", &a[0])
}
0xc0000b2000
0xc0000b2000
Có một cách khác để khởi tạo ra một Slices đó là dùng hàm make
, input là kiểu dữ liệu, len
và capacity
. Có 2 khái niệm mới là len
và cap
nên chú ý chỗ này, có thể hiểu len
là độ dài hiện tại cùa Slices đó còn cap
là phần bộ nhớ được cấp phát sẵn để cho trường hợp len
dài ra thêm.
package main
import "fmt"
func main() {
a := make([]int, 1, 3) // tạo một Slices có len là 1 và cap là 3
fmt.Println(len(a)) // 1
fmt.Println(cap(a)) // 3
a[0] = 10 // mình có thể sử dụng ngay a[0] vì len là 1. Nhưng không thể sử dụng thêm a[1], a[2] sẽ ra lỗi index out of range
a = append(a, 10) // tiếp theo là mình thêm 1 phần tử vào Slice. Như đã giải thích cap là phòng ngừa cho trường hợp này nên len = 2, cap = 3
a[1] = 11 // mình có thể dùng a[1] bình thường
a = append(a, 1, 2) // chuyện gì xảy ra nếu mình thêm vượt qua cả cap
fmt.Println(len(a)) // 7
fmt.Println(cap(a)) // 6 = 3 * 2 thường sẽ là gấp đôi cap của hiện tại
}
Điểm đặt biệt ở đây là khi mà append vượt qua cap thì Golang sẽ tìm một vùng nhớ có cap gấp đôi sau đó copy những phần tử hiện có qua. Có một cái hay hay là Slice có thể được khởi tạo tự Array và thay đổi giá trị của Array vì Slices đơn giản là một pointer nên nó có thể sửa được value của 1 biến Array. Bạn hãy thử tự code demo đoạn này nhé 😅
Tóm tắt
Bài này chỉ có vậy nhiêu đó cũng đủ giúp bạn tự tin dùng Array, Slices một cách tự tin
All rights reserved