📌

Giới Thiệu Go

Go là gì?

Go (Golang) là ngôn ngữ lập trình được phát triển bởi Google vào năm 2009. Go được thiết kế để đơn giản, hiệu quả và có khả năng xử lý đồng thời (concurrency) tuyệt vời.

💡 Tại sao chọn Go?
• Biên dịch nhanh, chạy nhanh
• Syntax đơn giản, dễ học
• Garbage collection tự động
• Built-in concurrency với Goroutines

Cài đặt Go

# macOS với Homebrew
brew install go

# Ubuntu/Debian
sudo apt update
sudo apt install golang-go

# Kiểm tra version
go version
# Output: go version go1.21.0 darwin/amd64

Hello World

package main

import "fmt"

func main() {
    fmt.Println("Xin chào, Gopher! 🐹")
}

Giải thích:
package main: Khai báo package chính
import "fmt": Import package để format output
func main(): Hàm chạy đầu tiên

📚

Khóa Học Golang Từ A Đến Z (20 Bài)

Goroutines & Channels

📘 Concurrency trong Go

Go nổi tiếng với model concurrency dựa trên Goroutines (lightweight threads) và Channels (để giao tiếp giữa các goroutines).

Goroutines

Goroutines là "lightweight threads" được quản lý bởi Go runtime. Chỉ cần thêm keyword go trước function call.

package main

import (
    "fmt"
    "time"
)

func sayHello(name string) {
    for i := 0; i < 3; i++ {
        fmt.Printf("Hello %s - %d\n", name, i)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    // Chạy goroutine
    go sayHello("Gopher")
    go sayHello("World")
    
    // Đợi goroutines hoàn thành
    time.Sleep(1 * time.Second)
    fmt.Println("Done!")
}

Channels

Channels cho phép goroutines gửi và nhận dữ liệu an toàn.

package main

import "fmt"

func worker(id int, jobs <-chan int, results chan<- int) {
    for job := range jobs {
        fmt.Printf("Worker %d processing job %d\n", id, job)
        results <- job * 2
    }
}

func main() {
    jobs := make(chan int, 5)
    results := make(chan int, 5)
    
    // Khởi tạo 3 workers
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }
    
    // Gửi 5 jobs
    for j := 1; j <= 5; j++ {
        jobs <- j
    }
    close(jobs)
    
    // Nhận kết quả
    for r := 1; r <= 5; r++ {
        fmt.Println("Result:", <-results)
    }
}
💡 Best Practice: Sử dụng sync.WaitGroup thay vì time.Sleep để đợi goroutines hoàn thành một cách chính xác.

Best Practices

Error Handling

Go không có exceptions, thay vào đó sử dụng multiple return values để xử lý lỗi.

package main

import (
    "errors"
    "fmt"
)

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("không thể chia cho 0")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("Lỗi:", err)
        return
    }
    fmt.Println("Kết quả:", result)
}
⚠️ Lưu ý: LUÔN kiểm tra error! Đừng bỏ qua error bằng _ trừ khi bạn biết chắc chắn điều bạn đang làm.

Naming Conventions

Public: Bắt đầu bằng chữ HOA (VD: GetUser)
Private: Bắt đầu bằng chữ thường (VD: getUserFromDB)
Constants: CamelCase, không dùng UPPER_CASE

package user

// Public - có thể access từ package khác
type User struct {
    ID   int
    Name string
}

// Public function
func GetUser(id int) (*User, error) {
    return getUserFromDB(id)
}

// Private - chỉ trong package này
func getUserFromDB(id int) (*User, error) {
    // implementation
    return &User{ID: id, Name: "John"}, nil
}

Struct và Methods

package main

import "fmt"

type Rectangle struct {
    Width  float64
    Height float64
}

// Method với value receiver
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Method với pointer receiver (có thể modify)
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

func main() {
    rect := Rectangle{Width: 10, Height: 5}
    fmt.Println("Area:", rect.Area()) // 50
    
    rect.Scale(2)
    fmt.Println("After scale:", rect.Area()) // 200
}
🌍

Ứng Dụng Thực Tế

REST API đơn giản

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type Response struct {
    Message string `json:"message"`
    Status  int    `json:"status"`
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
    response := Response{
        Message: "Xin chào từ Go API! 🐹",
        Status:  200,
    }
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(response)
}

func main() {
    http.HandleFunc("/api/hello", helloHandler)
    
    log.Println("Server running on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Chạy: go run main.go và truy cập http://localhost:8080/api/hello