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)
}