Functions in Go are declared with the func keyword, followed by the function name, parameters in parentheses, return type, and the function body. Go allows shorthand syntax for consecutive parameters of the same type: instead of func add(x int, y int), you write func add(x, y int).
Hàm trong Go được khai báo bằng từ khóa func, theo sau là tên hàm, danh sách tham số trong dấu ngoặc đơn, kiểu trả về, và khối hàm. Go cho phép viết tắt kiểu cho các tham số liên tiếp cùng kiểu: thay vì func add(x int, y int), bạn viết func add(x, y int).
1package main23import "fmt"45// Basic function declaration6func greet(name string) {7 fmt.Println("Hello, " + name)8}910// Function with return type11func add(a, b int) int {12 return a + bGo không hỗ trợ các tham số mặc định. Hãy sử dụng các tham số bao với giá trị mặc định hoặc nhận một struct tùy chỉnh để mô phỏng hành vi này.
Go allows functions to return multiple values. This is how Go handles error handling naturally — instead of throwing exceptions, functions return a result value and an error value. By convention, the error is always the last return value and is typically nil when there is no error.
Go cho phép một hàm trả về nhiều giá trị. Điều này là cách Go xử lý xử lý lỗi một cách tự nhiên — thay vì dùng exception, hàm trả về giá trị kết quả và giá trị lỗi. Theo quy ước, lỗi luôn là giá trị trả về cuối cùng và nó thường là nil khi không có lỗi.
1package main23import (4 "fmt"5 "strconv"6)78// Function returning multiple values: result and error9func divide(a, b float64) (float64, error) {10 if b == 0 {11 return 0, fmt.Errorf("division by zero")12 }Go allows you to name return values. These variables are initialized to the zero value of their type. A bare return statement returns the current named return values. This can make code more concise, but should be used sparingly in longer functions as it reduces clarity.
Go cho phép bạn đặt tên cho giá trị trả về. Các biến này được khởi tạo với giá trị zero của kiểu của chúng. Một return trống (bare return) sẽ trả về các giá trị được đặt tên hiện tại. Điều này có thể làm cho code ngắn hơn, nhưng nên dùng tiết chế trong các hàm dài — nó giảm rõ ràng.
1package main23import "fmt"45// Named return values6func minMax(arr []int) (min, max int) {7 if len(arr) == 0 {8 return9 }10 min, max = arr[0], arr[0]11 for _, v := range arr {12 if v < min {Dùng giá trị trả về được đặt tên một cách tiết chế. Chúng hữu ích cho các hàm ngắn, nhưng làm mờ rõ ràng trong các hàm dài — hãy dùng return rõ ràng thay thế.
Variadic functions accept a variable number of arguments of the same type. You specify this by placing ... before the final parameter type. Inside the function, the variadic parameter acts like a slice. You can also pass an existing slice to a variadic function using ....
Hàm variadic chấp nhận một số lượng đối số thay đổi của cùng một kiểu. Bạn chỉ định điều này bằng cách đặt ... trước kiểu tham số cuối cùng. Bên trong hàm, tham số variadic hoạt động như một slice. Bạn cũng có thể truyền một slice hiện có vào hàm variadic bằng cách sử dụng ....
1package main23import "fmt"45// Variadic function — accepts zero or more ints6func sum(nums ...int) int {7 total := 08 for _, n := range nums {9 total += n10 }11 return total12}In Go, functions are first-class values. You can assign them to variables, pass them as arguments to other functions, and return them from functions. The type of a function includes its parameter types and return type.
Trong Go, hàm là giá trị hạng nhất. Bạn có thể gán chúng cho biến, truyền chúng làm đối số cho hàm khác, và trả về chúng từ hàm. Kiểu của một hàm bao gồm các kiểu tham số và kiểu trả về của nó.
1package main23import "fmt"45// Function type: takes two ints, returns an int6type Operation func(int, int) int78// Implement some operations9func add(a, b int) int {10 return a + b11}12A closure is an anonymous function that encloses variables from its surrounding scope. Closures are often returned from factory functions. Each closure holds its own reference to the enclosed variables, creating independent state.
Closure là hàm ẩn danh bao bọc các biến từ phạm vi bao quanh nó. Closure thường được trả về từ hàm nhà máy (factory function). Mỗi closure giữ tham chiếu của riêng nó đến các biến bị bao bọc, tạo ra trạng thái riêng.
1package main23import "fmt"45// makeCounter returns a closure that increments and returns a counter6func makeCounter() func() int {7 count := 08 return func() int {9 count++10 return count11 }12}The init() function is a special function that runs automatically before main(). Go calls all init() functions in a package before any other code in that package runs. You can define multiple init() functions in the same file or different files — they run in the order determined by filename. Common use cases: registering database drivers, setting up configuration, validating requirements.
Hàm init() là một hàm đặc biệt chạy tự động trước main(). Go gọi tất cả các hàm init() trong một gói trước khi bất kỳ mã khác trong gói đó chạy. Bạn có thể định nghĩa nhiều hàm init() trong cùng một file hoặc file khác nhau — chúng chạy theo thứ tự xác định bởi tên file. Trường hợp sử dụng phổ biến: khởi tạo driver, thiết lập cấu hình, xác thực yêu cầu.
1package main23import (4 "fmt"5)67var (8 config map[string]string9 logFile string10)1112// First init (runs first alphabetically by file)Go chạy các hàm init() theo thứ tự xác định trong cùng một file. Nhưng nếu bạn có các file khác nhau trong cùng một gói, thứ tự sắp xếp các file theo tên. Đừng dựa vào thứ tự chính xác — nếu cần, hãy sử dụng một hàm setup rõ ràng.
Go allows you to define anonymous functions (without a name) and invoke them immediately. Anonymous functions are often passed as callbacks or to perform small tasks in a local context.
Go cho phép bạn định nghĩa hàm ẩn danh (không có tên) và gọi chúng ngay lập tức. Hàm ẩn danh thường được truyền làm callback hoặc để thực hiện công việc nhỏ trong ngữ cảnh địa phương.
1package main23import "fmt"45func main() {6 // Anonymous function invoked immediately7 func() {8 fmt.Println("Anonymous function executed immediately")9 }()1011 // Anonymous function with parameters12 func(name string, age int) {Key Takeaways
Điểm Chính
- Functions can return multiple values, making error handling naturalHàm có thể trả về nhiều giá trị, làm cho xử lý lỗi tự nhiên
- Variadic functions accept zero or more arguments using ... syntaxHàm variadic chấp nhận không hoặc nhiều đối số bằng cú pháp ...
- Go functions are first-class values that can be assigned and passed aroundHàm Go là giá trị hạng nhất có thể được gán và truyền
- Closures capture variables from their enclosing scope and maintain stateClosure bắt giữ biến từ phạm vi bao quanh và duy trì trạng thái
Practice
Test your understanding of this chapter
How do you declare a function in Go that returns multiple values?
Bạn khai báo hàm Go trả về nhiều giá trị như thế nào?
What does the ... operator do in the context func sum(nums ...int)?
Toán tử ... làm gì trong ngữ cảnh func sum(nums ...int)?
In Go, you can have multiple init() functions in the same package, and they all execute before main().
Trong Go, bạn có thể có nhiều hàm init() trong cùng một gói, và tất cả chúng đều thực thi trước main().
When you pass a slice to a variadic function using ..., the elements are unpacked and passed as separate arguments.
Khi bạn truyền một slice cho hàm variadic bằng ..., các phần tử được giải nén và truyền dưới dạng các đối số riêng biệt.
Complete the closure to capture a multiplier
Hoàn thành closure để bắt giữ một thừa số
func makeMultiplier(factor int) { return func(x int) int { return x * factor } }