Создание и импорт пакетов Go

GolangGolangBeginner
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В предыдущем разделе вы завершили простую программу на Go, которая содержала следующие строки кода:

package main
import "fmt"

Как понять эти две строки кода? Как эффективно использовать инструкции package и import?

В этом лабораторном занятии (LabEx) вы научитесь создавать и импортировать пакеты в Go. Это позволит вам организовать свой код в переиспользуемые модули, сделав ваши проекты на Go более поддерживаемыми и масштабируемыми.

Точки знания:

  • Определение и объявление пакета
  • Понимание экспортируемых (публичных) и неэкспортируемых (частных) идентификаторов
  • Различные формы импорта пакетов: одиночный, групповой, точечный, с псевдонимом и анонимный импорт
Это Guided Lab, который предоставляет пошаговые инструкции, чтобы помочь вам учиться и практиковаться. Внимательно следуйте инструкциям, чтобы выполнить каждый шаг и получить практический опыт. Исторические данные показывают, что это лабораторная работа уровня начальный с процентом завершения 84%. Он получил 84% положительных отзывов от учащихся.

Объявление и определение пакетов

Пакет в Go похож на модули в Python или библиотеки в C. Это набор файлов исходного кода, используемых для организации и повторного использования кода. Каждый файл на Go должен объявлять пакет в начале файла.

Примечание: Программа на Go должна иметь один и только один пакет с именем main, который служит точкой входа для выполнения. Без него программа не может создать исполняемый файл.

Основные моменты:

  1. Экспортируемые (публичные) идентификаторы: Идентификаторы (переменные, функции, типы и т.д.), начинающиеся с заглавной буквы, доступны из других пакетов. Их можно рассматривать как публичный интерфейс вашего пакета.
  2. Неэкспортируемые (частные) идентификаторы: Идентификаторы, начинающиеся с строчной буквы, доступны только внутри того же пакета. Они считаются внутренними деталями реализации пакета.
  3. Сцепление пакета: Все файлы в одной папке должны принадлежать одному и тому же пакету. Это обеспечивает сохранение связанного кода вместе.
  4. Соглашения по именованию пакетов: Имена пакетов должны быть строчными, короткими и описательными, избегая подчеркиваний или заглавных букв.

Давайте создадим собственный пользовательский пакет:

  1. Создайте папку с именем propagandist и файл propagandist.go внутри нее:

    mkdir ~/project/propagandist
    touch ~/project/propagandist/propagandist.go
  2. Напишите следующий код в файле propagandist.go:

    package propagandist
    
    var Shout = "I Love LabEx" // Public variable
    var secret = "I love the dress" // Private variable
    
    func Hit() string {
        return "Don't hit me, please!"
    }
    • Shout является публичной переменной, так как начинается с заглавной буквы. Это означает, что вы можете получить доступ к ней из других пакетов, которые импортируют propagandist.
    • secret является частной переменной, так как начинается со строчной буквы. Она может быть использована только внутри пакета propagandist.
    • Hit - это публичная функция, доступная из других пакетов.
  3. Инициализируйте модуль Go для пакета:

    cd ~/project/propagandist
    go mod init propagandist

    Эта команда инициализирует новый модуль Go в директории propagandist, который помогает управлять зависимостями пакета.

Импорт одного пакета

Для использования пакета propagandist создадим новую программу на Go. Этот шаг продемонстрирует, как импортировать и использовать один пакет в вашем коде на Go.

  1. Создайте новый файл на Go с именем pacExercise.go в папке проекта:

    touch ~/project/pacExercise.go
  2. Инициализируйте модуль Go для программы:

    cd ~/project
    go mod init pacExercise
  3. Обновите файл go.mod, чтобы включить зависимость от локального пакета. Выполните следующую команду в терминале:

    echo "replace propagandist =>./propagandist" >> go.mod

    Важно: Эта команда добавляет директиву replace в ваш файл go.mod. Это очень важно, так как она сообщает Go, что пакет propagandist должен быть взят из локальной директории ./propagandist, а не пытаться скачать его из удаленного репозитория. Вы должны выполнить эту команду в терминале, которая добавит строку replace propagandist =>./propagandist в ваш файл go.mod. Не пишите эту строку напрямую в файл вручную.

  4. Напишите следующий код в файле pacExercise.go, чтобы импортировать и использовать пакет propagandist:

    package main
    
    import (
        "fmt"
        "propagandist"
    )
    
    func main() {
        fmt.Println(propagandist.Shout) // Access the public variable
    }
    • Этот код импортирует пакет fmt для вывода информации и пакет propagandist.
    • Затем он обращается к публичной переменной Shout из пакета propagandist с помощью propagandist.Shout.
  5. Запустите программу:

    go mod tidy
    go run pacExercise.go

    Команда go mod tidy гарантирует, что ваш файл go.mod обновлен с учетом любых новых зависимостей. Команда go run pacExercise.go компилирует и выполняет программу.

    Ожидаемый вывод:

    I Love LabEx

Групповой импорт

При импорте нескольких пакетов можно использовать групповой импорт для улучшения читаемости и организации кода. Это вопрос стиля и не влияет на функциональность вашего кода.

  1. Измените файл pacExercise.go, чтобы использовать групповой импорт:

    package main
    
    import (
        "fmt"
        "propagandist"
    )
    
    func main() {
        fmt.Println(propagandist.Shout)
    }

    В приведенном выше фрагменте кода пакеты fmt и propagandist импортируются внутри одного блока import, заключенного в скобки. Это упрощает чтение и управление импортом нескольких пакетов. Это точно то же, что и в предыдущем примере, и показывает, как использовать синтаксис группового импорта.

  2. Запустите программу, чтобы убедиться, что она по-прежнему работает:

    go run pacExercise.go

    Программа должна выполниться без ошибок и выдать тот же результат, что и раньше.

Точковый импорт

При использовании точкового импорта можно опустить префикс имени пакета при вызове его функций или переменных. Это часто не рекомендуется в пользу явных имен пакетов, так как это может привести к конфликтам пространств имен и снизить читаемость. Однако полезно знать, что это такое.

  1. Измените файл pacExercise.go, чтобы использовать точковый импорт для пакета fmt:

    package main
    
    import. "fmt"
    import "propagandist"
    
    func main() {
        Println(propagandist.Shout) // No `fmt.` prefix needed
    }
    • Здесь import. "fmt" означает, что вы можете использовать функции и переменные из пакета fmt напрямую, без префикса fmt..
    • Например, вы используете Println вместо fmt.Println.
  2. Запустите программу:

    go run pacExercise.go

    Ожидаемый вывод:

    I Love LabEx

Импорт с псевдонимом

Вы можете назначить псевдоним импортируемому пакету для ясности или чтобы избежать конфликтов, когда два пакета имеют похожие имена. Это помогает сделать ваш код более читаемым и управлять коллизиями пространств имен.

  1. Измените файл pacExercise.go, чтобы назначить псевдоним io пакету fmt:

    package main
    
    import io "fmt"
    import "propagandist"
    
    func main() {
        io.Println(propagandist.Shout) // Use the alias `io` instead of `fmt`
    }
    • import io "fmt" создает псевдоним io для пакета fmt.
    • Теперь вы используете io.Println вместо fmt.Println.
  2. Запустите программу:

    go run pacExercise.go

Анонимный импорт

Анонимный импорт используется для импорта пакета ради его побочных эффектов, таких как выполнение его функции init(), без необходимости напрямую ссылаться на его экспортируемые идентификаторы. Это полезно для пакетов, которые регистрируют драйверы или выполняют другие задачи инициализации.

  1. Измените файл pacExercise.go, чтобы включить анонимный импорт пакета time:

    package main
    
    import (
        "fmt"
        "propagandist"
        _ "time" // Anonymous import
    )
    
    func main() {
        fmt.Println(propagandist.Shout)
    }
    • import _ "time" - это анонимный импорт. Подчеркивание _ используется как пустой идентификатор, сообщающий компилятору, что вы импортируете пакет ради его побочных эффектов и не будете напрямую ссылаться на его содержимое в своем коде.
    • Функция init() пакета time будет выполнена при запуске этой программы. Пакет time не имеет каких - то особых видимых побочных эффектов здесь, однако многие пакеты используют этот подход для регистрации драйверов баз данных или настройки конфигурации.
  2. Запустите программу:

    go run pacExercise.go

    Ожидаемый вывод:

    I Love LabEx

Резюме

В этом практическом занятии вы узнали:

  1. Как создавать и определять пользовательские пакеты в Go, инкапсулируя повторно используемый код.
  2. Разницу между публичными (экспортируемыми) и приватными (неэкспортируемыми) идентификаторами и то, как они влияют на доступность.
  3. Различные способы импорта пакетов и их области применения:
    • Импорт одного пакета за раз: Импортирование по одному пакету за раз.
    • Групповой импорт: Импортирование нескольких пакетов в одном блоке для лучшей организации.
    • Точковый импорт: Импортирование пакета и использование его идентификаторов напрямую без префикса имени пакета. (Используйте с осторожностью)
    • Импорт с псевдонимом: Переименование импортированных пакетов для лучшей читаемости или избежания конфликтов имен.
    • Анонимный импорт: Импортирование пакета только ради его побочных эффектов, таких как инициализация.
  4. Роль функции init() в пакетах и то, как анонимный импорт может вызвать ее выполнение.

Завершив это практическое занятие, вы теперь можете эффективно структурировать и управлять проектами на Go с использованием пакетов. Вы можете создавать повторно используемые модули, контролировать доступ к идентификаторам и лучше организовать свой код, что приведет к созданию более поддерживаемых и масштабируемых приложений на Go.

Summary

In this lab, you learned:

  1. How to create and define custom packages in Go, encapsulating reusable code.
  2. The difference between public (exported) and private (unexported) identifiers and how they impact accessibility.
  3. Various ways to import packages, each with its use case:
    • Single-item import: Importing one package at a time.
    • Grouped import: Importing multiple packages in a single block for better organization.
    • Dot import: Importing a package and using its identifiers directly without the package name prefix. (Use with caution)
    • Alias import: Renaming imported packages for better readability or to avoid naming conflicts.
    • Anonymous import: Importing a package solely for its side effects, such as initialization.
  4. The role of the init() function in packages and how anonymous imports can trigger its execution.
  5. The detailed workings of Go's initialization process, including:
    • How package-level variables are initialized before init() functions
    • The guaranteed execution order of init() functions across dependent packages
    • How multiple init() functions work within a package
    • The complete initialization flow from dependent packages to the main function

By completing this lab, you are now equipped to structure and manage Go projects using packages effectively. You can create reusable modules, control access to identifiers, better organize your code, and understand the initialization process, leading to more maintainable and scalable Go applications.