Hàm trong Go được khai báo với func, và một tính năng đặc trưng là trả về nhiều giá trị — một hàm có thể trả về nhiều giá trị cùng lúc. Điều này được dùng phổ biến khắp nơi, đặc biệt cho idiom (result, error) định nghĩa cách xử lý lỗi của Go.
Hàm cơ bản
func add(a int, b int) int { // tham số kèm kiểu, rồi đến kiểu trả về
return a + b
}
func greet(name string) string {
return "Hello, " + name
}
// rút gọn cho các tham số cùng kiểu: func add(a, b int) int
Trả về nhiều giá trị — tính năng đặc trưng
func divide(a, b int) (int, error) { // trả về CẢ kết quả LẪN error
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil // error nil = thành công
}
// bên gọi xử lý cả hai — pattern xử lý lỗi phổ biến của Go
result, err := divide(10, 2)
if err != nil {
log.Fatal(err) // xử lý lỗi
}
fmt.Println(result)
Trả về (value, error) LÀ idiom để xử lý lỗi trong Go — thay vì exception, các hàm trả về error dưới dạng giá trị mà bên gọi kiểm tra tường minh. Điều này khiến việc xử lý lỗi trở nên hiển nhiên và không thể âm thầm bỏ qua.
Pattern comma-ok
// nhiều built-in trả về (value, ok) — một boolean cho "có thành công không?"
value, ok := myMap["key"] // ok = false nếu key không tồn tại
if ok { ... }
v, ok := someInterface.(string) // type assertion với ok
Giá trị trả về có tên (named return values)
func split(sum int) (x, y int) { // named returns
x = sum * 4 / 9
y = sum - x
return // "naked return" — trả về các giá trị có tên
}
Hàm variadic
func sum(nums ...int) int { // nhận số lượng int bất kỳ
total := 0
for _, n := range nums {
total += n
}
return total
}
sum(1, 2, 3) // 6
sum(nums...) // trải một slice thành các tham số
Hàm là first-class
var op func(int, int) int = add // gán hàm cho biến
func apply(fn func(int) int, x int) int { return fn(x) } // truyền như tham số
Tại sao điều này quan trọng
Hàm trong Go là trung tâm, và trả về nhiều giá trị là một trong những tính năng đặc trưng của ngôn ngữ — chúng cho phép idiom (result, error) chính là cách tiếp cận xử lý lỗi của Go (kiểm tra lỗi-dưới-dạng-giá-trị tường minh thay vì exception).
Pattern này, được dùng trong hầu hết mọi chương trình Go, khiến việc xử lý lỗi trở nên hiển nhiên và có chủ đích.
Idiom comma-ok liên quan (value, ok :=) xuất hiện khắp nơi (truy cập map, type assertion, nhận từ channel).
Hiểu việc trả về nhiều giá trị, pattern error, named return, hàm variadic, và hàm first-class là thiết yếu để đọc và viết Go idiomatic — và triết lý lỗi-dưới-dạng-giá-trị là một trong những khác biệt khái niệm quan trọng nhất giữa Go và các ngôn ngữ dựa trên exception.
