Khái niệm và ứng dụng hàm trong ngôn ngữ Go

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ý...")
}

Thẻ: Go Functions closures

Đăng vào ngày 14 tháng 6 lúc 20:06