0
0
Lập trình
Admin Team
Admin Teamtechmely

Tìm Hiểu Hàm init() trong Go: Cách Sử Dụng và Thực Tiễn

Đăng vào 7 tháng trước

• 4 phút đọc

Tìm Hiểu Hàm init() trong Go

Khi làm việc với ngôn ngữ lập trình Go, đôi khi chúng ta cần thực hiện một số thao tác cơ bản trước khi bắt đầu công việc chính. Hãy tưởng tượng như một tiếng chuông trường học—khi chuông reo, mọi người đều vào lớp và bắt đầu học.

1. Khái Niệm Cơ Bản về Hàm init()

  • Hàm init() là một hàm đặc biệt trong Go.
  • Nó chạy tự động trước khi hàm main() được gọi.
  • Bạn không cần phải gọi nó; Go sẽ tự động gọi cho bạn.

Ví dụ về Hàm init()

go Copy
package main
import "fmt"

func init() {
    fmt.Println("Tôi chạy trước hàm main()")
}

func main() {
    fmt.Println("Tôi là hàm chính")
}

Kết quả:

Copy
Tôi chạy trước hàm main()
Tôi là hàm chính

Giải thích:

  • Hàm init() chạy trước.
  • Sau đó, hàm main() bắt đầu.

Ví dụ Khác với Biến

go Copy
package main
import "fmt"

var a = 10

func init() {
    fmt.Println("Trước khi thay đổi, a =", a)
    a = 20
    fmt.Println("Sau khi thay đổi, a =", a)
}

func main() {
    fmt.Println("Trong hàm main, a =", a)
}

Kết quả:

Copy
Trước khi thay đổi, a = 10
Sau khi thay đổi, a = 20
Trong hàm main, a = 20

Tại đây, init() đã thay đổi biến trước khi main() sử dụng nó.

2. Nhiều Hàm init()

  • Bạn có thể viết nhiều hơn một hàm init() trong cùng một tệp.
  • Bạn có thể viết chúng trong nhiều tệp khác nhau.
  • Bạn cũng có thể có init() trong các gói được nhập khẩu.

Ví dụ:

go Copy
func init() {
    fmt.Println("Hàm init đầu tiên")
}

func init() {
    fmt.Println("Hàm init thứ hai")
}

func main() {
    fmt.Println("Hàm chính đang chạy")
}

Kết quả:

Copy
Hàm init đầu tiên
Hàm init thứ hai
Hàm chính đang chạy

👉 Giống như nhiều tiếng chuông trước lớp:

  • Tiếng chuông đầu tiên (init()) → Chuẩn bị.
  • Tiếng chuông thứ hai (init()) → Ngồi vào chỗ.
  • Giáo viên (main()) → Bắt đầu bài học.

3. Thứ Tự Thực Thi

Go luôn theo thứ tự giống nhau:

Copy
Biến trong gói → init() → main()

Ví dụ:

go Copy
var x = setValue()

func setValue() int {
    fmt.Println("setValue() được gọi")
    return 10
}

func init() {
    fmt.Println("Bên trong hàm init()")
}

func main() {
    fmt.Println("Bên trong hàm main()")
}

Kết quả:

Copy
setValue() được gọi
Bên trong hàm init()
Bên trong hàm main()

Các biến được chuẩn bị trước, sau đó là init(), và cuối cùng là main().

4. Phân Tích Nâng Cao

  • ✅ Bạn có thể viết nhiều hàm init().
  • ⚠️ Tuy nhiên, không nên lạm dụng chúng—điều này làm cho mã khó đọc.
  • ✅ Khởi tạo biến xảy ra trước khi init() được gọi.
  • ✅ Các gói được nhập khẩu sẽ chạy hàm init() của chúng trước hàm init() của gói chính.
  • ❌ Bạn có thể gọi init() theo cách thủ công, nhưng đó là thực hành xấu.

👉 Hãy tưởng tượng: Nếu người giữ trường tự gọi chuông hai lần, mọi người sẽ bị bối rối 😵. Đó là lý do tại sao Go tự động gọi nó.

5. Ví Dụ Thực Tế

Giả sử ứng dụng của bạn cần một kết nối cơ sở dữ liệu. Thay vì thiết lập trong main(), bạn có thể chuẩn bị nó trong init().

go Copy
package config
import "fmt"

var DBConnection string

func init() {
    fmt.Println("Đang thiết lập kết nối cơ sở dữ liệu...")
    DBConnection = "mysql://user:password@localhost:3306/mydb"
}
go Copy
package main
import (
    "fmt"
    "config"
)

func main() {
    fmt.Println("Hàm chính đang chạy")
    fmt.Println("Sử dụng DB:", config.DBConnection)
}

Kết quả:

Copy
Đang thiết lập kết nối cơ sở dữ liệu...
Hàm chính đang chạy
Sử dụng DB: mysql://user:password@localhost:3306/mydb

👉 Giống như đội ngũ hậu trường chuẩn bị sân khấu 🎤 trước khi các diễn viên đến, init() chuẩn bị chương trình.

6. Thực Hành Tốt Nhất

✅ Sử Dụng Tốt Hàm init()

  • Tải cấu hình (cơ sở dữ liệu, môi trường).
  • Khởi tạo biến.
  • Đăng ký các tuyến đường, plugin hoặc lệnh.

❌ Sử Dụng Xấu Hàm init()

  • Không đặt logic chính ở đây.
  • Không lạm dụng nó.
  • Không tự gọi nó.

Nguyên tắc: Giữ cho init() ngắn gọn, sạch sẽ và chỉ để chuẩn bị.

✅ Thứ Tự Thực Thi:

Copy
Biến → init() → main()

✅ Bạn có thể có nhiều hàm init() không giới hạn (nhưng nên giữ ở mức tối thiểu).
✅ Các gói được nhập khẩu chạy init() của chúng trước.
❌ Không gọi init() theo cách thủ công.

Hãy nghĩ về init() như đội ngũ hậu trường chuẩn bị vở kịch trước khi các diễn viên xuất hiện trên sân khấu.

7. Câu Hỏi Thường Gặp (FAQ)

Hàm init() có thể đặt ở đâu?

Hàm init() có thể được đặt ở bất kỳ đâu trong tệp Go, và bạn có thể có nhiều hàm init() trong cùng một tệp hoặc trong nhiều tệp khác nhau.

Có thể gọi hàm init() từ hàm main() không?

Không, bạn không nên gọi hàm init() từ hàm main(), vì Go sẽ tự động gọi nó khi cần thiết.

Tại sao không nên lạm dụng hàm init()?

Lạm dụng init() có thể làm cho mã của bạn trở nên khó hiểu và khó bảo trì hơn, vì nó có thể làm ngắt quãng luồng thực thi tự nhiên của chương trình.

Cảm ơn bạn đã đọc bài viết này! Hãy áp dụng những kiến thức về hàm init() để cải thiện mã của bạn trong Go.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào