KHOÁ HỌC Phần 1 — Nền tảng Kiến thức nền bắt buộc

Kiến thức nền bắt buộc

Đối tượng: Người chưa biết gì về lập trình. Mục tiêu: hiểu 8 khái niệm "bảng chữ cái" của Go trước khi viết dòng code thật đầu tiên ở chương sau.

Biến (Variable)

chỗ chứa dữ liệu có tên gọi:

var name string = "Web-Server"  // Khai báo đầy đủ
age := 25                        // Cách viết ngắn (Go tự đoán kiểu)

Kiểu dữ liệu (Type)

  • string — chuỗi văn bản ("hello")
  • int — số nguyên (42)
  • bool — đúng/sai (true/false)

Điều khiển luồng — if/else, for, switch

Go có đúng 3 cấu trúc điều khiển luồng. Không cần dấu ngoặc () quanh điều kiện, nhưng bắt buộc {} quanh khối lệnh (kể cả khi khối chỉ có 1 dòng — khác C/Java/JS).

if/else:

if tuoi >= 18 {
    fmt.Println("Đã đủ tuổi")
} else {
    fmt.Println("Chưa đủ tuổi")
}

for — Go chỉ có duy nhất for, không có while/do-while riêng như ngôn ngữ khác:

// for kiểu C truyền thống — có khởi tạo, điều kiện, bước tăng
for i := 0; i < 5; i++ {
    fmt.Println(i)
}

// for kiểu "while" — chỉ giữ điều kiện, bỏ khởi tạo/bước tăng
n := 0
for n < 5 {
    n++
}

// for vô hạn — tự dừng bằng break
for {
    if daXong {
        break
    }
}

// for range — lặp qua slice/map/string (sẽ dùng rất nhiều ở các chương sau)
for i, v := range []string{"a", "b", "c"} {
    fmt.Println(i, v) // 0 a / 1 b / 2 c
}

switch — mỗi case tự dừng, không "rơi" tiếp xuống case dưới như C/Java (nên gần như không bao giờ cần viết break trong switch của Go):

switch diem {
case 10, 9:
    fmt.Println("Giỏi")
case 8, 7:
    fmt.Println("Khá")
default:
    fmt.Println("Cần cố gắng")
}

⚠️ Quy tắc dễ vấp nhất khi mới học: khai báo mà không dùng = LỖI BIÊN DỊCH

Go coi 1 biến hoặc 1 package import ra mà không hề dùng tớilỗi, không phải cảnh báo — chương trình không build được, không chạy được:

func main() {
    x := 5   // ❌ lỗi: "x declared and not used" — nếu không dùng x ở đâu cả
}

Đây là lý do các ví dụ về sau đôi khi có dòng như _ = servers — chỉ để "đánh lừa" trình biên dịch tạm thời trong lúc khung chương trình chưa hoàn chỉnh, sẽ xoá đi khi biến được dùng thật.

Hàm (Function)

một khối lệnh có tên, nhận đầu vào, trả đầu ra:

func cong(a int, b int) int {
    return a + b
}

Struct — "Cái hộp chứa nhiều thứ"

Gộp nhiều biến liên quan thành một khối:

type NguoiDung struct {
    Ten   string
    Tuoi  int
}

Con trỏ (*) — "Địa chỉ nhà" của biến

  • s = giá trị (một bản sao)
  • *s = giá trị thật tại địa chỉ đó
  • &s = lấy địa chỉ của s

👉 Vì sao cần? Khi muốn sửa giá trị gốc chứ không phải bản sao.

nil — "trống", "chưa trỏ đi đâu cả"

nil là giá trị rỗng dành cho pointer, slice, map, interface, channel, function — không dùng được cho int/string/bool (những kiểu đó có zero value riêng: 0, "", false, xem lại nếu quên ở mục Kiểu dữ liệu).

var p *int            // p là nil — con trỏ khai báo xong nhưng CHƯA trỏ tới đâu cả
fmt.Println(p == nil) // true

fmt.Println(*p) // 💥 panic: runtime error: invalid memory address or nil pointer dereference

👉 Lỗi runtime phổ biến nhất với người mới học Go: dùng *p (dereference — "mở ra xem giá trị bên trong") khi p đang là nil. Luôn if p != nil { ... } trước khi dùng con trỏ nếu không chắc chắn nó đã được gán giá trị thật.

Package main + import

Mọi chương trình Go chạy được đều phải có:

package main         // Đây là chương trình chính

import "fmt"         // "Mượn" thư viện fmt để in ra màn hình

func main() {        // Hàm main = điểm bắt đầu
    fmt.Println("Xin chào!")
}

Đã đủ nền. Chương sau bắt đầu bài toán thật — 1 dự án hoàn chỉnh dùng đúng 8 khái niệm này làm điểm xuất phát.

← Về mục lục