Понимание пакетов в Golang

Будь вы опытным разработчиком Golang или только начинаете работать с Golang, вы, вероятно, часто слышали слова «пакет» (package) и «модуль» (module) или, по крайней мере, сталкивались с ними в каком-нибудь материале.

Поначалу мне было сложно разобраться с этими двумя понятиями, но не в том, каковы их определения, а в том, что они означают для экосистемы, в которой вы будете работать, создавая/прописывая программы на Golang.

В этой статье мы поговорим о том, что такое пакеты в языке программирования Go (Golang) и о нескольких важных концепциях, связанных с ними.

Пакеты — Packages

Пакет — это файл или группа файлов с пространством имен и некоторым кодом или связанным с ним кодом. Это означает, что пакет может находиться в одном файле, например math.go, или в нескольких файлах, таких как add.go, subctract.go, multiply.go, то есть во многих файлах или в одном файле, например, с именем package math.

Пакет будет иметь окружающий каталог, например:

Содержимое файла math.go может выглядеть примерно так:

Весь код нашего математического пакета находится в одном файле
Весь код нашего математического пакета находится в одном файле

Если мы решили разбить этот математический пакет на несколько файлов, мы можем создать три файла add.go, subctract.go, multiply.go со следующим содержимым…

add.go из пакета math:

subtract.go из пакета math:

multiply.go из пакета math:

Взглянув на все три результирующих файла, вы, возможно, уже заметили общий знаменатель — все они используют одно и то же пространство имен пакета math. Конечно, вы, скорее всего, никогда не встретите человека, делающего что-то подобное, если только он не разбивает очень большие файлы на несколько файлов. Понимание концепции общего пространства имен очень важно для того, о чем мы будем говорить дальше.

Экспортируемые и локальные функции/методы

Идея написания пакетов в Golang заключается в создании модульных фрагментов кода, которыми можно делиться в своих проектах или с другими разработчиками для использования в их собственных проектах. Так держать, Golang! Мне нравится твоя щедрая натура.

Для того чтобы это произошло, и чтобы это произошло безопасно, мы можем захотеть раскрыть некоторые части нашего кода как внешние API, которые будут использоваться, а также сохранить некоторые аспекты пакета более скрытыми и не такими доступными. Некоторые языки предоставляют такие конструкции, как public, private, protected, чтобы помочь в этом, но в Golang концепции публичных (public) и частных (private) API вытекают из того, как мы называем наши функции, методы и свойства. Давайте рассмотрим пример.

Иллюстрация экспортируемых и локальных функций
Иллюстрация экспортируемых и локальных функций

Если посмотреть на иллюстрацию выше, у нас есть две функции, названные одинаково, с одним отличием: одна из них — multiply со строчной буквы, а другая начинается с прописной Multiply, и это тонкое различие является отличием между локальной и экспортируемой функцией в Golang. Вы можете гадать, кто из них кто Вы можете быть правы, судя по их структуре, но, тем не менее, в Golang, когда вы называете что-то полностью строчными буквами, это локализовано и не может быть доступно вне этого пакета (помните, что такое пакет? посмотрите еще раз?). С другой стороны, все, что начинается с заглавной буквы, может быть доступно как внутри, так и вне пакета, в котором оно было определено/объявлено.

Так что если мы опубликовали наш пакет сегодня (мы рассмотрим публикацию пакетов в ближайшее время), мы можем импортировать этот математический пакет и получить доступ к Multiply, но попытка получить доступ к multiply определенно вызовет ошибку!

Попытка получить доступ к экспортированной и неэкспортированной функции из пакета math
Попытка получить доступ к экспортированной и неэкспортированной функции из пакета math

В то время как мы можем получить доступ к multiply в том же пространстве имен, даже в другом файле!

Эти концепции могут стать разницей между красиво и творчески структурированным кодом на Go и беспорядочными программами. Следует отметить, что math здесь использовалось как иллюстративное имя пакета, НЕ ИСПОЛЬЗУЙТЕ ЕГО в реальных или игровых приложениях, так как в Golang уже есть встроенный математический пакет, и это наверняка приведет к нежелательному поведению (но вы можете попробовать, если вам интересно).

Резюме

  • Пакет можно представить как файл, имеющий имя (вверху) и содержащий некоторый связанный код
  • Это также может быть группа файлов с одним и тем же пространством имен package, содержащих связанный код
  • Не разбивайте преждевременно пакеты на несколько файлов, если только это не крайне необходимо, например, если файлом трудно управлять, или если у вас есть динамически генерируемый код во время выполнения (мы обсудим генерацию кода в ближайшее время) и т. д. Кроме того, даже если вы разделите пакеты на разные файлы, они должны находиться в одной директории, иначе вы испортите импорт в дальнейшем.
  • В Golang понятия приватных и публичных функций, методов и типов подразумеваются в зависимости от того, как вы называете эти конструкции. Если они начинаются с заглавной буквы, то к ним могут обращаться пакеты, не входящие в текущий пакет, если со строчной буквы, то они становятся «приватными» (private) и недоступными/неприкосновенными за пределами текущего пакета.

Вот и все! Поехали, поехали, поехали Вы узнали немного Golang сегодня, спасибо вам большое, что следите за нами! В моей следующей статье мы рассмотрим модули и то, как они связаны с концепцией пакетов, до скорой встречи.

Оригинал статьи
Опубликовано 29 августа 2024 в 00:32
Обновлено 29 августа 2024 в 00:32
Категория: Блог
Теги: