Array và Slice
Array — Mảng cố định
Array có kích thước cố định và là value type (copy khi gán).
var a [5]int // [0, 0, 0, 0, 0]
b := [3]string{"Go", "là", "tuyệt"}
c := [...]int{1, 2, 3, 4} // [...] tự đếm = [4]int
fmt.Println(len(b)) // 3
// Array là value type: gán thì copy toàn bộ
x := [3]int{1, 2, 3}
y := x // copy hoàn toàn
y[0] = 99
fmt.Println(x[0]) // 1 — x không thay đổi
Slice — Mảng động (dùng nhiều hơn)
Slice là reference type gồm 3 trường bên trong: (pointer, len, cap).
// Tạo slice
s := []int{1, 2, 3, 4, 5} // literal
s2 := make([]int, 3) // [0,0,0] len=3 cap=3
s3 := make([]int, 0, 10) // [] len=0 cap=10
fmt.Println(len(s), cap(s)) // 5 5
append — Thêm phần tử
s := []int{1, 2, 3}
s = append(s, 4) // [1,2,3,4]
s = append(s, 5, 6, 7) // [1,2,3,4,5,6,7]
// Nối hai slice
a := []int{1, 2}
b := []int{3, 4}
c := append(a, b...) // [1,2,3,4]
Slice expression — Cắt slice
a := []int{0, 1, 2, 3, 4, 5}
// 0 1 2 3 4 5
a[1:4] // [1, 2, 3] — từ index 1 đến 3 (không tính 4)
a[:3] // [0, 1, 2] — từ đầu đến index 2
a[3:] // [3, 4, 5] — từ index 3 đến cuối
a[:] // toàn bộ slice
// QUAN TRỌNG: slice con dùng chung bộ nhớ với slice gốc!
b := a[1:4]
b[0] = 99
fmt.Println(a[1]) // 99 — a cũng bị thay đổi!
copy — Sao chép an toàn
src := []int{1, 2, 3, 4, 5}
dst := make([]int, len(src))
n := copy(dst, src) // trả về số phần tử được copy
// dst và src giờ độc lập
Nil slice vs Empty slice
var s1 []int // nil slice — s1 == nil là true
s2 := []int{} // empty slice — s2 != nil
s3 := make([]int, 0)
// Cả ba đều có len = 0
// Nil slice và empty slice hoạt động giống nhau với append
s1 = append(s1, 1) // OK
Các thủ thuật Slice thường dùng
// Xóa phần tử tại index i (giữ thứ tự)
s = append(s[:i], s[i+1:]...)
// Xóa nhanh (không giữ thứ tự)
s[i] = s[len(s)-1]
s = s[:len(s)-1]
// Lọc (filter)
var result []int
for _, v := range s {
if v%2 == 0 {
result = append(result, v)
}
}
example.go
package main
import (
"fmt"
"sort"
)
func filter(s []int, f func(int) bool) []int {
var result []int
for _, v := range s {
if f(v) {
result = append(result, v)
}
}
return result
}
func mapSlice(s []int, f func(int) int) []int {
result := make([]int, len(s))
for i, v := range s {
result[i] = f(v)
}
return result
}
func main() {
nums := []int{5, 2, 8, 1, 9, 3, 7, 4, 6}
// Sort
sorted := make([]int, len(nums))
copy(sorted, nums)
sort.Ints(sorted)
fmt.Println("Gốc: ", nums)
fmt.Println("Sorted:", sorted)
// Filter số chẵn
evens := filter(nums, func(n int) bool { return n%2 == 0 })
fmt.Println("Số chẵn:", evens)
// Map: bình phương
squares := mapSlice(nums, func(n int) int { return n * n })
fmt.Println("Bình phương:", squares)
// Xóa phần tử index 2
s := []string{"A", "B", "C", "D", "E"}
s = append(s[:2], s[3:]...)
fmt.Println("Sau khi xóa C:", s)
}