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
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ả:
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
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ả:
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
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ả:
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:
Biến trong gói → init() → main()
Ví dụ:
go
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ả:
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
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
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ả:
Đ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:
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.