Пакет состоит из файлов Go, которые находятся в том же каталоге и имеют одинаковое выражение пакета в начале. Вы можете добавить дополнительные функции из пакетов, чтобы усложнить программы. Некоторые пакеты доступны в стандартной библиотеке Go и устанавливаются вместе с Go. Другие можно установить с помощью команды go get
в Go. Также вы можете создавать собственные пакеты Go, создавая файлы Go в том же каталоге, где вы хотите разместить общий код, используя необходимое выражение пакета.
В этом обучающем руководстве вы научитесь писать пакеты Go для использования в других программных файлах.
Пакеты пишутся так же, как любые другие файлы Go. Пакеты могут содержать определения функций, типов и переменных, которые могут использоваться в других программах Go.
Перед созданием нового пакета необходимо перейти в рабочее пространство Go. Обычно его можно найти по адресу gopath
. Например, в этом обучающем модуле мы назовем пакет greet
. Для этого мы создали каталог с именем greet
с путем gopath
в рабочем пространстве проекта. Допустим наша организация называется gopherguides
, и мы хотим создать пакет greet
в каталоге организации, используя Github в качестве хранилища кода. В этом случае наш каталог будет выглядеть следующим образом:
└── $GOPATH
└── src
└── github.com
└── gopherguides
Каталог greet
находится внутри каталога gopherguides
:
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── greet
Наконец, мы можем добавлять в каталог первый файл. Обычно первичному
файлу или файлу точки входа
в пакете присваивается имя каталога. В этом случае мы создадим файл с именем greet.go
в каталоге greet
:
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── greet
└── greet.go
После создания файла мы можем начать писать код для повторного использования или совместного использования в нескольких проектах. В данном случае мы создадим функцию с именем Hello
, которая выводит текст Hello World
.
Откройте файл greet.go
в текстовом редакторе и добавьте следующий код:
package greet
import "fmt"
func Hello() {
fmt.Println("Hello, World!")
}
Разделим первый файл на части. В первой строке каждого файла нужно указать имя пакета
, с которым вы работаете. Поскольку вы находитесь в пакете greet
, вы используете ключевое слово package
, за которым идет имя пакета:
package greet
Так компилятор будет рассматривать все содержание файла как часть пакета greet
.
Затем вы декларируете все другие пакеты, которые вам нужно использовать, с помощью выражения import
. В этом файле вы используете только пакет fmt
:
import "fmt"
В заключение вы создадите функцию Hello
. Она будет использовать пакет fmt
для вывода текста Hello, World!
:
func Hello() {
fmt.Println("Hello, World!")
}
Теперь вы записали пакет greet
и можете использовать его в любом другом создаваемом вами пакете. Создадим новый пакет, в котором будет использоваться ваш пакет greet
.
Вы создадите пакет с именем example
, и это означает, что вам требуется каталог с именем example
. Создайте пакет в организации gopherguides
, чтобы структура каталогов выглядела следующим образом:
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── example
Теперь у вас есть каталог нового пакета, и вы можете создать файл точки входа. Поскольку это исполняемая программа, следует присвоить файлу точки входа имя main.go
:
└── $GOPATH
└── src
└── github.com
└── gopherguides
└── example
└── main.go
Откройте в текстовом редакторе файл main.go
и добавьте следующий код для вызова пакета greet
:
package main
import "github.com/gopherguides/greet"
func main() {
greet.Hello()
}
Поскольку вы импортируете пакет, вам нужно вызвать функцию, сославшись на имя пакета в точечной нотации. Точечная нотация — это практика, предусматривающая постановку точки .
между именем используемого пакета и ресурсом этого пакета, который вы хотите использовать. Например, в пакете greet
вы можете использовать функцию Hello
в качестве ресурса. Если вы хотите вызвать этот ресурс, вы можете использовать точечную нотацию greet.Hello()
.
Теперь вы можете открыть терминал и запустить команду из командной строки:
- go run main.go
В этом случае вы получите следующий результат:
OutputHello, World!
Чтобы посмотреть, как использовать переменные в пакете, добавим определение переменной в файл greet.go
:
package greet
import "fmt"
var Shark = "Sammy"
func Hello() {
fmt.Println("Hello, World!")
}
Откройте файл main.go
и добавьте следующую выделенную строку для вызова переменной из greet.go
в функции fmt.Println()
:
package main
import (
"fmt"
"github.com/gopherguides/greet"
)
func main() {
greet.Hello()
fmt.Println(greet.Shark)
}
После повторного запуска программы:
- go run main.go
Вывод должен выглядеть следующим образом:
OutputHello, World!
Sammy
В заключение определим тип в файле greet.go
. Вы создадите тип Octopus
с полями name
и color
, а также функцию, которая будет выводить поля при вызове:
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!")
}
Откройте файл 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())
}
После создания экземпляра типа Octopus
с помощью выражения oct := greet.Octopus
вы сможете получить доступ к функциям и полям типа в пространстве имен файла main.go
. Это позволит вам записать oct.String()
в последнюю строку без вызова greet
. Например, вы можете вызвать одно из полей типа, например oct.Color
, не ссылаясь на имя пакета greet
.
Метод String
типа Octopus
использует функцию fmt.Sprintf
для создания предложения и возвращает
результат в виде строки вызывающему компоненту (в данном случае, основной программе).
При запуске программы вы получите следующий результат:
- go run main.go
OutputHello, World!
Sammy
The octopus's name is "Jesse" and is the color orange.
Создавая метод String
в типе Octopus
, вы получаете возможность многократно выводить информацию о своем пользовательском типе. Если вы захотите изменить поведение этого метода, вам нужно будет только отредактировать этот метод.
Возможно вы заметили, что все декларации в вызванном вами файле greet.go
были указаны заглавными буквами. В Go отсутствует концепция модификаторов public
, private
и protected
, как в других языках. Видимость для внешних элементов определяется использованием заглавных букв. Типы, переменные, функции и другие элементы, которые начинаются с заглавной буквы, находятся в публичной зоне видимости. Символ, видимый вне пакета, считается экспортируемым
.
Если вы добавите в Octopus
новый метод с именем reset
, вы можете вызвать его из пакета greet
, но не из файла main.go
, который находится вне пакета greet
:
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!")
}
Если вы попробуете вызвать метод reset
из файла 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()
}
Вы получите следующую ошибку компиляции:
Outputoct.reset undefined (cannot refer to unexported field or method greet.Octopus.reset)
Чтобы выполнить экспорт
функции reset
из Octopus
, нужно сделать заглавной букву R
в имени метода reset
:
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!")
}
В результате вы можете вызвать метод Reset
из другого пакета без сообщения об ошибке:
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())
}
Теперь, если вы запустите программу:
- go run main.go
Результат будет выглядеть следующим образом:
OutputHello, World!
Sammy
The octopus's name is "Jesse" and is the color orange
The octopus's name is "" and is the color .
Вызывая метод Reset
, вы очистили всю информацию в полях Name
и Color
. При вызове метода String
он не будет выводить никакого текста, где появляются Name
и Color
, поскольку теперь эти поля пустые.
Написание пакета Go аналогично написанию любого другого файла Go, однако его размещение в другом каталоге позволяет изолировать код для повторного использования в любом месте. В этом обучающем руководстве мы показали, как написать определения пакета, продемонстрировали использование этих определений в другом файле Go и описали варианты хранения пакета для доступа к нему.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!