Hàm trong Go
Hàm trong Go được sử dụng để tái sử dụng mã nguồn, tổ chức và đóng gói các đoạn mã có cùng mục đích. Hàm trong Go được coi là "đối tượng bậc nhất" (first-class citizen), có thể gán cho biến, truyền như tham số hoặc trả về từ các hàm khác.
Định nghĩa hàm
func ten_ham([danh_sach_tham_so]) (kieu_tra_ve) {
noi_dung_ham
}
- Tên hàm: Được tạo bởi chữ cái, số và dấu gạch dưới, không bắt đầu bằng số.
- Tham số: Gồm tên biến và kiểu dữ liệu của nó.
- Kiểu trả về: Có thể là một hoặc nhiều kiểu dữ liệu.
- Nội dung hàm: Đoạn mã thực hiện chức năng.
Ví dụ định nghĩa hàm
func thongTinTuoi(ten string, tuoi int) (string, int) {
tuoiKeTiep := tuoi + 1
return fmt.Sprintf("%s năm nay %d tuổi", ten, tuoi), tuoiKeTiep
}
Gọi hàm
Một hàm được gọi bằng cách sử dụng tên hàm kèm cặp ngoặc tròn chứa tham số (nếu có).
package main
import "fmt"
func main() {
inChao()
}
func inChao() {
fmt.Println("Xin chào!")
}
Truyền tham số
Tham số tiêu chuẩn
Hàm có thể nhận tham số và xử lý chúng để đưa ra kết quả khác nhau.
package main
import "fmt"
func main() {
ketQua := chao("Nguyen")
fmt.Println(ketQua)
}
func chao(ten string) string {
return fmt.Sprintf("Hello %s", ten)
}
Thu gọn tham số cùng kiểu
Các tham số cùng kiểu có thể được viết ngắn gọn.
func chao(ten, diaChi string) string {
return fmt.Sprintf("Hello %s, địa chỉ: %s", ten, diaChi)
}
Tham số biến đổi
Go hỗ trợ tham số dạng slice với từ khóa `...`.
func tinhTong(ten string, so ...int) string {
tong := 0
for _, s := range so {
tong += s
}
return fmt.Sprintf("%s tính tổng: %v", ten, tong)
}
Trả về giá trị
Trả về đơn
Một hàm có thể trả về một giá trị duy nhất.
func cong(x, y int) int {
return x + y
}
Trả về đa
Hàm cũng có thể trả về nhiều giá trị.
func phepToan(x, y int) (int, int) {
return x + y, x - y
}
Tên giá trị trả về
Các giá trị trả về có thể được đặt tên trực tiếp trong khai báo hàm.
func tinhTongHieu(x, y int) (tong int, hieu string) {
tong = x + y
hieu = fmt.Sprintf("Hiệu là %d", x-y)
return
}
Phạm vi biến
Biến toàn cục
Biến toàn cục có thể được truy cập từ mọi nơi trong chương trình.
var so int = 10
func hienThiSo() {
fmt.Println("Số toàn cục:", so)
}
Biến cục bộ
Biến cục bộ chỉ tồn tại trong phạm vi mà nó được khai báo.
func xuLy() {
if true {
bien := 5
fmt.Println("Biến bên trong khối if:", bien)
}
// fmt.Println(bien) // Sai vì biến không tồn tại ở đây
}
Cách truyền tham số
Truyền theo giá trị
Khi truyền theo giá trị, bản sao của dữ liệu sẽ được gửi vào hàm.
type nguoi struct {
hoTen string
tuoi int
}
func hienThiThongTin(n nguoi) {
fmt.Printf("Tên: %s, Tuổi: %d\n", n.hoTen, n.tuoi)
}
Truyền theo tham chiếu
Khi truyền theo tham chiếu, địa chỉ của dữ liệu sẽ được gửi vào hàm.
func tangTuoi(n *nguoi) {
n.tuoi++
}
Hàm bậc cao
Hàm bậc cao là hàm nhận hoặc trả về hàm khác.
func tinh(a, b int, phep func(int, int) int) int {
return phep(a, b)
}
func cong(x, y int) int {
return x + y
}
Hàm ẩn danh
Hàm ẩn danh không có tên và thường được sử dụng trong các trường hợp tạm thời.
goi := func(x, y int) int { return x * y }
fmt.Println(goi(3, 4))
Bế cấu
Bế cấu là hàm có thể truy cập vào biến của hàm bao ngoài ngay cả khi hàm bao ngoài đã hoàn thành.
func taoHamCong() func(int) int {
bien := 0
return func(x int) int {
bien += x
return bien
}
}
Lệnh defer
Lệnh defer đảm bảo rằng biểu thức được gọi sau khi hàm bao quanh hoàn thành.
func xuLyDuLieu() {
defer fmt.Println("Kết thúc xử lý.")
fmt.Println("Bắt đầu xử lý...")
}