之前就很好奇,像是 github.com/go-sql-driver/mysql 到底是如何做到只需寫以下幾行,就能夠連線 mysql
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
// ...
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306/my-db)")
後來去查,原來是因為 init() 這個 function
根據我查到的資料, init() 雖然是 private function,但和 main() 一樣,都是特殊 function
main() 是程式的主程式; init() 則是在 main() 之前執行,每個 import 進來的 package 都會執行的 function
例如說以下這個 go module:
package main
import (
_ "play-ground/foobar"
)
func main() {
}
-- foo/foo.go --
package foo
import "fmt"
func init() {
fmt.Println("foo")
}
-- bar/bar.go --
package bar
import "fmt"
func init() {
fmt.Println("bar")
}
-- foobar/foobar.go --
package foobar
import (
_ "play-ground/bar"
_ "play-ground/foo"
)
-- go.mod --
module play-ground
因為 main 有引用到 play-ground/foobar,而 foobar 又引用了 foo 和 bar 兩個 package,依照順序,雖然 main 並沒有 print 任何東西,但最終程式會輸出:
bar
foo
而 init() 還有一個特殊性——一個 package 允許多個 init()
故以下的程式是正常的,且兩個 init() 都能執行
package main
import (
_ "play-ground/foo"
)
func main() {
}
-- foo/foo.go --
package foo
import "fmt"
func init() {
fmt.Println("1st init")
}
func init() {
fmt.Println("2nd init")
}
-- go.mod --
module play-ground
參考資料
asong, (2021, June 7). Go语言中的神奇函数init. Golang梦工厂. https://asong.cloud/go%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E7%A5%9E%E5%A5%87%E5%87%BD%E6%95%B0init/
沒有留言:
張貼留言