So schreiben Sie Pakete in Go

Ein Paket besteht aus Go-Dateien, die sich in demselben Verzeichnis befinden und am Anfang dieselbe Paketanweisung haben. Sie können zusätzliche Funktionen aus Paketen einbinden, um Ihre Programme komplexer zu gestalten. Einige Pakete sind über die Go-Standardbibliothek verfügbar und werden daher mit Ihrer Go-Installation installiert. Andere können mit dem Befehlgo getvon Go installiert werden. Sie können auch Ihre eigenen Go-Pakete erstellen, indem Sie Go-Dateien in demselben Verzeichnis erstellen, in dem Sie Code mithilfe der erforderlichen Paketanweisung freigeben möchten.

Dieses Tutorial führt Sie durch das Schreiben von Go-Paketen zur Verwendung in anderen Programmdateien.

Voraussetzungen

  • Richten Sie eine Go-Programmierumgebung nach einem der Tutorials aus derHow To Install and Set Up a Local Programming Environment for Go-Serie ein. Erstellen Sie Ihren Go Workspace gemäß Schritt 5 in den Tutorials zur lokalen Programmierumgebung. Lesen Sie den ersten Abschnitt Schreiben und Importieren von Paketen, um das Beispiel und die Namenskonventionen in diesem Artikel zu befolgen.

  • Lesen Sie unseren ArtikelUnderstanding the GOPATH, um Ihr Wissen über den GOPATH zu vertiefen.

Pakete schreiben und importieren

Das Schreiben eines Pakets entspricht dem Schreiben einer beliebigen anderen Go-Datei. Pakete können Definitionen von Funktionen,types undvariables enthalten, die dann in anderen Go-Programmen verwendet werden können.

Bevor wir ein neues Paket erstellen, müssen wir uns in unserem Go-Arbeitsbereich befinden. Dies liegt normalerweise unter unserengopath. In diesem Tutorial nennen wir beispielsweise das Paketgreet. Zu diesem Zweck haben wir in unseremgopath unter unserem Projektbereich ein Verzeichnis mit dem Namengreet erstellt. Wenn unsere Organisationgopherguides wäre und wir das Paketgreet unter der Organisation erstellen möchten, während wir Github als Code-Repository verwenden, würde unser Verzeichnis folgendermaßen aussehen:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides

Das Verzeichnisgreetbefindet sich im Verzeichnisgopherguides:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── greet

Schließlich können wir die erste Datei in unser Verzeichnis aufnehmen. Es wird allgemein angenommen, dass die Dateiprimary oderentry point in einem Paket nach dem Namen des Verzeichnisses benannt ist. In diesem Fall erstellen wir eine Datei mit dem Namengreet.go im Verzeichnisgreet:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── greet
                    └── greet.go

Mit der erstellten Datei können wir beginnen, unseren Code zu schreiben, den wir wiederverwenden oder projektübergreifend freigeben möchten. In diesem Fall erstellen wir eine Funktion namensHello, dieHello World ausgibt.

Öffnen Sie die Dateigreet.goin Ihrem Texteditor und fügen Sie den folgenden Code hinzu:

greet.go

package greet

import "fmt"

func Hello() {
    fmt.Println("Hello, World!")
}

Lassen Sie uns diese erste Datei aufschlüsseln. Die erste Zeile jeder Datei benötigt den Namen derpackage, in denen Sie arbeiten. Da Sie sich im Paketgreetbefinden, verwenden Sie das Schlüsselwortpackage, gefolgt vom Namen des Pakets:

package greet

Dadurch wird der Compiler angewiesen, alles in der Datei als Teil des Paketsgreetzu behandeln.

Als Nächstes deklarieren Sie alle anderen Pakete, die Sie mit der Anweisungimportverwenden müssen. Sie verwenden in dieser Datei nur eine - das Paketfmt:

import "fmt"

Zuletzt erstellen Sie die FunktionHello. Es wird das Paketfmt verwendet, umHello, World! auszudrucken:

func Hello() {
    fmt.Println("Hello, World!")
}

Nachdem Sie das Paketgreetgeschrieben haben, können Sie es in jedem anderen von Ihnen erstellten Paket verwenden. Erstellen Sie ein neues Paket, in dem Sie das Paketgreetverwenden.

Sie erstellen ein Paket mit dem Namenexample. Dies bedeutet, dass Sie ein Verzeichnis mit dem Namenexample benötigen. Erstellen Sie dieses Paket in der Organisation Ihresgopherguides, sodass die Verzeichnisstruktur folgendermaßen aussieht:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                    └── example

Nachdem Sie das Verzeichnis für Ihr neues Paket erstellt haben, können Sie die Einstiegspunktdatei erstellen. Da dies ein ausführbares Programm sein wird, wird es als bewährte Methode angesehen, die Einstiegspunktdateimain.go zu benennen:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── example
                    └── main.go

Öffnen Sie in Ihrem Texteditormain.go und fügen Sie den folgenden Code hinzu, um das Paketgreet aufzurufen:

main.go

package main

import "github.com/gopherguides/greet"

func main() {
    greet.Hello()
}

Da Sie ein Paket importieren, müssen Sie die Funktion aufrufen, indem Sie den Paketnamen in Punktnotation referenzieren. Dot notation ist die Praxis, einen Punkt. zwischen dem Namen des von Ihnen verwendeten Pakets und der Ressource in dem Paket, das Sie verwenden möchten, einzufügen. In Ihremgreet-Paket haben Sie beispielsweise dieHello-Funktion als Ressource. Wenn Sie diese Ressource aufrufen möchten, verwenden Sie die Punktnotationgreet.Hello().

Jetzt können Sie Ihr Terminal öffnen und das Programm in der Befehlszeile ausführen:

go run main.go

In diesem Fall erhalten Sie die folgende Ausgabe:

OutputHello, World!

Um zu sehen, wie Sie Variablen in einem Paket verwenden können, fügen wir Ihrergreet.go-Datei eine Variablendefinition hinzu:

greet.go

package greet

import "fmt"

var Shark = "Sammy"

func Hello() {
    fmt.Println("Hello, World!")
}

Öffnen Sie als Nächstes Ihremain.go-Datei und fügen Sie die folgende hervorgehobene Zeile hinzu, um die Variable vongreet.go in einerfmt.Println()-Funktion aufzurufen:

main.go

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)
}

Sobald Sie das Programm erneut ausführen:

go run main.go

Sie erhalten folgende Ausgabe:

OutputHello, World!
Sammy

Lassen Sie uns abschließend auch einen Typ in der Dateigreet.godefinieren. Sie erstellen den TypOctopus mit den Feldernname undcolor und einer Funktion, die die Felder beim Aufruf ausgibt:

greet.go

package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func Hello() {
    fmt.Println("Hello, World!")
}

Öffnen Siemain.go, um am Ende der Datei eine Instanz dieses Typs zu erstellen:

main.go

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())
}

Sobald Sie mitoct := greet.Octopus eine Instanz vom TypOctopuserstellt haben, können Sie auf die Funktionen und Felder des Typs im Namespace der Dateimain.gozugreifen. Auf diese Weise können Sieoct.String() in die letzte Zeile schreiben, ohnegreet aufzurufen. Sie können beispielsweise auch eines der Typfelder wieoct.Color aufrufen, ohne auf den Namen des Paketsgreet zu verweisen.

Die MethodeString für den TypOctopus verwendet die Funktionfmt.Sprintf, um einen Satz zu erstellen, undreturns das Ergebnis, eine Zeichenfolge, für den Aufrufer (in diesem Fall Ihre Hauptleitung) Programm).

Wenn Sie das Programm ausführen, erhalten Sie folgende Ausgabe:

go run main.go
OutputHello, World!
Sammy
The octopus's name is "Jesse" and is the color orange.

Durch Erstellen derString-Methode fürOctopus haben Sie jetzt eine wiederverwendbare Möglichkeit, Informationen zu Ihrem benutzerdefinierten Typ auszudrucken. Wenn Sie das Verhalten dieser Methode in Zukunft ändern möchten, müssen Sie nur diese eine Methode bearbeiten.

Exportierter Code

Möglicherweise haben Sie bemerkt, dass alle Deklarationen in der von Ihnen aufgerufenengreet.go-Datei groß geschrieben wurden. Go hat nicht das Konzept vonpublic,private oderprotected Modifikatoren wie andere Sprachen. Die Sichtbarkeit nach außen wird durch die Großschreibung gesteuert. Typen, Variablen, Funktionen usw., die mit einem Großbuchstaben beginnen, sind außerhalb des aktuellen Pakets öffentlich verfügbar. Ein Symbol, das außerhalb des Pakets sichtbar ist, wird alsexported betrachtet.

Wenn SieOctopus eine neue Methode hinzufügen, diereset heißt, können Sie sie aus dem Paketgreet aufrufen, jedoch nicht aus der Dateimain.go, die sich außerhalb vonmain.gobefindet. t4) s Paket:

greet.go

package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func (o *Octopus) reset() {
    o.Name = ""
    o.Color = ""
}

func Hello() {
    fmt.Println("Hello, World!")
}

Wenn Sie versuchen,reset aus der Dateimain.go aufzurufen:

main.go

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())

    oct.reset()
}

Sie erhalten den folgenden Kompilierungsfehler:

Outputoct.reset undefined (cannot refer to unexported field or method greet.Octopus.reset)

Umexport diereset Funktionalität vonOctopus zu erhalten, aktivieren Sie dieR inreset:

greet.go

package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func (o *Octopus) Reset() {
    o.Name = ""
    o.Color = ""
}

func Hello() {
    fmt.Println("Hello, World!")
}

Infolgedessen können SieReset von Ihrem anderen Paket aus aufrufen, ohne eine Fehlermeldung zu erhalten:

main.go

package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())

    oct.Reset()

    fmt.Println(oct.String())
}

Nun, wenn Sie das Programm ausführen:

go run main.go

Sie erhalten folgende Ausgabe:

OutputHello, World!
Sammy
The octopus's name is "Jesse" and is the color orange
The octopus's name is "" and is the color .

Durch Aufrufen vonReset haben Sie alle Informationen in den FeldernName undColor gelöscht. Wenn Sie die MethodeString aufrufen, wird nichts gedruckt, woName undColor normalerweise angezeigt werden, da die Felder jetzt leer sind.

Fazit

Das Schreiben eines Go-Pakets entspricht dem Schreiben einer beliebigen anderen Go-Datei. Wenn Sie es jedoch in einem anderen Verzeichnis ablegen, können Sie den Code isolieren, der an einer anderen Stelle wiederverwendet werden soll. In diesem Lernprogramm wurde das Schreiben von Definitionen in ein Paket behandelt, die Verwendung dieser Definitionen in einer anderen Go-Programmdatei erläutert und die Optionen für die Aufbewahrung des Pakets für den Zugriff darauf erläutert.