Bagian deklaratif dari mengimpor paket ke Go agak membosankan dan biasa saja. Anda hanya perlu menentukan arahan import
dan mendaftar paket yang diimpor. IDE modern melakukan pekerjaan ini untuk Anda - mereka sendiri mengganti paket di bagian ini, yang sangat nyaman. Selain itu, mereka menutup blok ini sehingga tidak mengganggu tampilan kode. Saya menyarankan Anda untuk memperluas blok ini dan mempelajarinya dengan cermat - mungkin Anda akan menemukan sesuatu yang tidak biasa di sana:
package main import ( "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" _ "github.com/vigo5190/goimports-example/c" )
Jika impor standar, impor dengan sinonim dan _
saya bertemu, lalu impor dari .
Saya belum pernah melihat sebelumnya.
Sebagai permulaan, perlu diingat bagaimana program on Go diluncurkan.
Hal pertama dan terpenting - pada akar proyek (untuk pustaka dan paket lain) terletak file main.go
, yang, ketika dikembangkan, dijalankan oleh
go run main.go
Fitur khas dari file ini adalah bahwa paket yang dideklarasikan di dalamnya harus main
.
package main import ( "fmt" ) func main() { fmt.Println("Hello habr.com!") }
Pada dasarnya, titik masuk ke program adalah func main()
dalam paket main
. Tetapi perilaku ini bisa diretas sedikit. Fungsi func init()
ditemukan untuk ini. Fungsi ini akan mengeksekusi sebelum menjalankan func main()
. Fungsi ini juga dapat ditulis dalam paket Anda. Itu akan selalu dieksekusi ketika sebuah paket diimpor (tepatnya, itu akan dieksekusi setelah pertama kali sebuah paket diimpor dalam program Anda). Perlu juga dipahami bahwa init()
akan dieksekusi ketika pengujian paket ini dijalankan.
Contoh Paket
Paket a
hanya mengekspor variabel, tetapi tidak menginisialisasi itu.
github.com/vigo5190/goimports-example/a Paket b
mengekspor variabel dan menginisialisasi ke init()
.
github.com/vigo5190/goimports-example/b package b var Foo string func init() { Foo = "bar" }
Paket c
mengekspor variabel, menginisialisasi ke init()
dan menampilkan nilai di stdout.
github.com/vigo5190/goimports-example/c package c import "fmt" var Foo string func init() { Foo = "bar" fmt.Printf("%#v\n", Foo) }
Impor "sederhana"
Dalam contoh ini, kami mengimpor 2 paket dan menampilkan nilai variabel yang diekspor ke stdout.
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", b.Foo) }
Kami mendapatkan
go run main.go "" "bar"
Apa yang sebenarnya terjadi dalam kode ini. Di bagian import
, 2 paket a
dan b
diimpor. Dalam paket a
variabel dengan nilai default dinyatakan (untuk string - string kosong). Dalam paket b
, nilai variabel diinisialisasi dalam init()
nilai "bar"
. Untuk mengakses variabel dari setiap paket, gunakan entri formulir <_>.<_>
.
Impor sinonim
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/b" bar "github.com/vigo5190/goimports-example/a" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", foo.Foo) fmt.Printf("%#v\n", bar.Foo) }
Kami mendapatkan
go run main.go "" "bar" ""
Seperti yang Anda lihat dari contoh, paket b
diberi sinonim foo
. Dalam hal ini, paket a
diimpor beberapa kali - yang kedua kali di bawah bar
alias.
Paket diimpor dengan menetapkan sinonim dalam beberapa kasus:
- Nama paket yang diimpor tidak nyaman / jelek / ... dan saya ingin menggunakan yang lain;
- Nama yang diimpor bersinggungan dengan nama paket lain;
- Saya ingin mengganti paket dengan mulus - antarmuka paket harus cocok.
Contoh penggunaan sinonim yang dapat dibenarkanMisalnya, ketika mengimpor github.com/sirupsen/logrus
:
package db import( log "github.com/sirupsen/logrus" )
Garisbawahi Impor
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" _ "github.com/vigo5190/goimports-example/c" ) func main() { fmt.Printf("%#v\n", a.Foo) }
Kami mendapatkan
go run main.go "bar" ""
Seperti yang ditunjukkan kode, kami mengimpor dua paket: a
dan c
. Dalam hal ini, paket c
didahului oleh _
dan paket itu sendiri tidak digunakan dengan cara apa pun. Teknik ini digunakan untuk mengeksekusi init()
dari sebuah paket.
Dalam contoh kita, "bar"
muncul di output pada baris pertama, karena output ini ada dalam fungsi inisialisasi paket c
.
Contoh Penggunaan yang Dibenarkan _Misalnya, saat mengimpor github.com/lib/pq
:
package db import( _ "github.com/lib/pq" )
di init()
lib/pq
kodenya adalah:
func init() { sql.Register("postgres", &Driver{}) }
yang akan mendaftarkan pengemudi.
Impor c dot
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", Foo) }
Kami mendapatkan
go run main.go "" "bar"
Impor dengan titik menambahkan semua bidang yang diekspor dari paket ke cakupan saat ini (lebih tepatnya, cakupan file). Dan sekarang Anda dapat bekerja dengan bidang paket yang diimpor seolah-olah mereka berada di paket Anda.
Opsi ini harus digunakan dengan sangat hati-hati - contoh di bawah ini.
Contoh 1 package main import ( . "fmt" ) func main() { Println("Hello, habr.com!") }
Kami mendapatkan:
Hello, habr.com!
Contoh 2 package main import ( . "fmt" . "math" ) func main() { Printf("%v\n", Sqrt(9)) }
Kami mendapatkan:
3
Impor dengan titik (dan kesalahan)
package main import ( "fmt" . "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", Foo) }
Kami mendapatkan
go run main.go
Seperti yang Anda lihat dari output, ketika mengimpor paket dengan bidang berpotongan ke dalam lingkup saat ini, kami mendapatkan kesalahan kompilasi.
Karena itu, pikirkan lagi sebelum menggunakan impor semacam itu - Anda bisa mendapatkan kesalahan yang sama sekali tidak terduga.
Total
Terlepas dari batasan sintaksis yang ketat, Anda dapat melakukan cukup banyak hal yang tidak standar di Go. Fitur impor yang dibahas di atas menunjukkan bahwa hanya dengan beberapa operator, Anda dapat sangat mengubah perilaku suatu program. Hal utama, saat menggunakan semua peluang ini, adalah jangan menembak diri sendiri . Dan ingat bahwa lebih baik menulis kode yang sederhana dan mudah dipahami daripada kode yang kompleks dan โkerenโ.
PS
Contoh kode untuk dimainkan ada di github .