4 Möglichkeiten, ein Paket in Go zu importieren

Der deklarative Teil des Imports von Paketen in Go ist ziemlich langweilig und banal. Sie müssen nur die import angeben und die importierten Pakete auflisten. Moderne IDEs erledigen diese Arbeit für Sie - sie selbst ersetzen Pakete in diesem Abschnitt, was sehr praktisch ist. Außerdem reduzieren sie diesen Block, damit er die Codeansicht nicht beeinträchtigt. Ich rate Ihnen, diesen Block zu erweitern und sorgfältig zu studieren - vielleicht finden Sie dort etwas Ungewöhnliches:


  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" ) 

Wenn der Standardimport mit einem Synonym importiert und _ ich getroffen habe, dann importiere von . Ich habe noch nie gesehen.


Für den Anfang ist es wichtig, sich daran zu erinnern, wie Programme auf Go gestartet werden.
Das erste und wichtigste - im Stammverzeichnis des Projekts (ansonsten für Bibliotheken und Pakete) liegt die Datei main.go , die bei ihrer Entwicklung vom Befehl gestartet wird


 go run main.go 

Eine Besonderheit dieser Datei ist, dass das darin deklarierte Paket main muss.


 package main import ( "fmt" ) func main() { fmt.Println("Hello habr.com!") } 

Im Wesentlichen ist der Einstiegspunkt in das Programm func main() im Hauptpaket. Aber dieses Verhalten kann ein bisschen gehackt werden . func init() Funktion func init() erfunden. Diese Funktion wird ausgeführt, bevor func main() . Diese Funktion kann auch in Ihre Pakete geschrieben werden. Es wird immer ausgeführt, wenn ein Paket importiert wird (genauer gesagt, es wird ausgeführt, wenn ein Paket zum ersten Mal in Ihr Programm importiert wird). Es ist auch sinnvoll zu verstehen, dass init() ausgeführt wird, wenn die Tests dieses Pakets ausgeführt werden.


Paketbeispiele


Paket a exportiert die Variable nur, initialisiert sie jedoch nicht.


github.com/vigo5190/goimports-example/a
 package a var Foo string 

Paket b exportiert die Variable und initialisiert sie mit init() .


github.com/vigo5190/goimports-example/b
 package b var Foo string func init() { Foo = "bar" } 

Paket c exportiert die Variable, initialisiert sie mit init() und zeigt den Wert in stdout an.


github.com/vigo5190/goimports-example/c
 package c import "fmt" var Foo string func init() { Foo = "bar" fmt.Printf("%#v\n", Foo) } 

Importieren Sie "einfach"


In diesem Beispiel importieren wir 2 Pakete und geben die Werte der exportierten Variablen an stdout aus.


 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) } 

Wir bekommen


 go run main.go "" "bar" 

Was passiert eigentlich in diesem Code? Im import werden 2 Pakete a und b importiert. In Paket a Variable mit einem Standardwert deklariert (für Zeichenfolgen - eine leere Zeichenfolge). In Paket b wurde der Variablenwert in init() Wert "bar" initialisiert. Verwenden Sie einen Eintrag in der Form <_>.<_> , um auf die Variablen der einzelnen Pakete <_>.<_> .


Synonym importieren


 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) } 

Wir bekommen


 go run main.go "" "bar" "" 

Wie Sie dem Beispiel foo können, wird Paket b das Synonym foo zugewiesen. In diesem Fall wurde Paket a importiert - das zweite Mal unter der Aliasleiste.


Pakete werden in mehreren Fällen durch Setzen von Synonymen importiert:


  • Der Name des importierten Pakets ist unpraktisch / hässlich / ... und ich möchte ein anderes verwenden.
  • Der Name des importierten Pakets überschneidet sich mit dem Namen eines anderen Pakets.
  • Ich möchte das Paket nahtlos ersetzen - die Paketschnittstellen müssen übereinstimmen.

Beispiel für die berechtigte Verwendung eines Synonym

Zum Beispiel beim Importieren von github.com/sirupsen/logrus :


 package db import( log "github.com/sirupsen/logrus" ) 

Import unterstreichen


 package main import ( "fmt" "github.com/vigo5190/goimports-example/a" _ "github.com/vigo5190/goimports-example/c" ) func main() { fmt.Printf("%#v\n", a.Foo) } 

Wir bekommen


 go run main.go "bar" "" 

Wie der Code zeigt, importieren wir zwei Pakete: a und c . In diesem Fall steht vor dem Paket c _ und das Paket selbst wird in keiner Weise verwendet. Diese Technik wird verwendet, um init() aus einem Paket auszuführen.


In unserem Beispiel wurde in der Ausgabe in der ersten Zeile "bar" angezeigt, da sich diese Ausgabe in der Paketinitialisierungsfunktion befindet. c


Begründetes Verwendungsbeispiel _

Zum Beispiel beim Importieren von github.com/lib/pq :


 package db import( _ "github.com/lib/pq" ) 

In init() lib/pq lautet der Code:


 func init() { sql.Register("postgres", &Driver{}) } 

Dadurch wird der Treiber registriert.


C-Punkt importieren


 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) } 

Wir bekommen


 go run main.go "" "bar" 

Beim Importieren mit einem Punkt werden alle exportierten Felder des Pakets zum aktuellen Bereich hinzugefügt (genauer gesagt zum Dateibereich). Und jetzt können Sie mit den Feldern des importierten Pakets so arbeiten, als wären sie in Ihrem Paket.


Diese Option sollte sehr sorgfältig verwendet werden - ein Beispiel unten.


Beispiel 1
 package main import ( . "fmt" ) func main() { Println("Hello, habr.com!") } 

Wir bekommen:


 Hello, habr.com! 

Beispiel 2
 package main import ( . "fmt" . "math" ) func main() { Printf("%v\n", Sqrt(9)) } 

Wir bekommen:


 3 

Import mit Punkt (und Fehler)


 package main import ( "fmt" . "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", Foo) } 

Wir bekommen


 go run main.go # command-line-arguments ./main.go:7:2: Foo redeclared during import "github.com/vigo5190/goimports-example/b" previous declaration during import "github.com/vigo5190/goimports-example/a" ./main.go:7:2: imported and not used: "github.com/vigo5190/goimports-example/b" 

Wie Sie der Ausgabe entnehmen können, wird beim Importieren von Paketen mit sich überschneidenden Feldern in den aktuellen Bereich ein Kompilierungsfehler angezeigt.


Denken Sie daher noch einmal darüber nach, bevor Sie einen solchen Import verwenden - es kann völlig unerwartet zu einem Fehler kommen.


Insgesamt


Trotz der strengen Syntaxbeschränkungen können Sie in Go eine Menge nicht standardmäßiger Dinge tun. Die oben beschriebenen Importfunktionen zeigen, dass Sie mit nur wenigen Operatoren das Verhalten eines Programms stark ändern können. Die Hauptsache, wenn Sie all diese Möglichkeiten nutzen, ist, sich nicht in den Fuß zu schießen . Und denken Sie daran, dass es besser ist, einfachen und verständlichen Code zu schreiben als komplexen und „coolen“.


PS


Beispiele für Code zum Spielen finden Sie auf dem Github .

Source: https://habr.com/ru/post/de413563/


All Articles