+1

[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, lencapacity. Có 2 khái niệm mới là lencap 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

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí