Як писати Go-пакети

Пакет Go складається з Go-файлів, розташованих в одній і тій же директорії, на початку яких є однаковий вираз package. Пакети, що підключаються до програм, дозволяють розширювати їх можливості. Деякі пакети входять до складу стандартної бібліотеки Go. А це означає, що вони, якщо ви користуєтеся Go, вже у вас встановлені. Інші пакети встановлюють за допомогою команди go get. Можна, крім того, писати власні Go-пакети, створюючи файли в особливих директоріях, і дотримуючись правил оформлення пакетів.

Даний матеріал являє собою керівництво з розробки Go-пакетів, які можна підключати до інших файлів.

Попередні вимоги

  • Налаштуйте програмне оточення Go (про те, як це зробити, можна дізнатися тут). Створіть робочий простір Go (цьому присвячений п’ятий пункт вищезгаданого матеріалу). У наступному розділі цього матеріалу ви зможете знайти приклади, які рекомендується відтворити у себе. Так ви зможете краще з ними розібратися.
  • Для того щоб поглибити свої знання з GOPATH – погляньте на цей матеріал.

Написання та імпорт пакетів

Написання коду пакету – це те ж саме, що і написання звичайного коду на Go. Пакети можуть містити оголошення функцій, типів і змінних, які потім можуть бути використані в інших Go-програмах.

Перш ніж ми зможемо приступити до створення нового пакету, нам потрібно перейти в робочий простір Go. Він знаходиться по шляху, який задається змінною GOPATH. Наприклад, нехай наша організація називається gopherguides. При цьому ми, як репозиторій, використовуємо GitHub. Це призводить до того, що у нас, по шляху, який задається GOPATH, є наступна структура папок:

Ми збираємося назвати пакет, який будемо розробляти в цьому керівництві, greet. Для того щоб це зробити – створимо директорію greet в директорії gopherguides. В результаті наявна структура папок буде мати наступний вигляд:

Тепер ми готові до того, щоб додати в директорію greet перший файл. Зазвичай файл, який є вхідною точкою (entry point) пакета, називають так само, як названа директорія пакету. В даному випадку це означає, що ми, в директорії greet, створюємо файл greet.go:

У цьому файлі ми можемо писати код, який хочемо багаторазово використовувати в наших проектах. В даному випадку ми створимо функцію Hello, яка виводить текст Hello, World !.

Відкрийте файл greet.go в текстовому редакторі і додайте в нього наступний код:

Розберемо вміст цього файлу. Перший рядок кожного файлу повинен містити ім’я пакету, в якому ми працюємо. Так як ми знаходимося в пакеті greet – тут використовується ключове слово package, за яким слідує ім’я пакету:

Це повідомляє компілятору про те, що він повинен сприймати все, що знаходиться в файлі, як частину пакету greet.

Далі виконується імпорт необхідних пакетів за допомогою виразу import. В даному випадку нам потрібен всього один пакет – fmt:

І, нарешті, ми створюємо функцію Hello. Вона буде використовувати можливості пакету fmt для виведення на екран рядку Hello, World !:

Тепер, після того, як створений пакет greet, ви можете скористатися ним в будь-якому іншому пакеті. Створимо новий пакет, в якому скористаємося пакетом greet.

А саме, ми створимо пакет example. Для цього будемо виходити з тих же припущень, з яких виходили, створюючи пакет greet. Для початку створимо папку example в папці gopherguides:

Тепер створюємо файл, який є вхідною точкою пакету. Даний пакет ми розглядаємо як виконувану програму, а не як пакет, код якого планується використовувати в інших пакетах. Файли, які є вхідними точками програм, прийнято називати main.go:

Відкрийте в редакторі файл main.go і внесіть в нього наступний код, який дозволяє скористатися можливостями пакету greet:

Ми імпортували в файлі main.go пакет greet, а це значить, що для виклику функції, оголошеної в цьому пакеті, нам знадобиться скористатися точковою нотацією. Точкова нотація – це конструкція, в якій між ім’ям пакету і ім’ям ресурсу цього пакету, який потрібно використовувати, ставиться крапка. Наприклад, в пакеті greet роль ресурсу грає функція Hello. Якщо потрібно викликати цю функцію – використовується точкова нотація: greet.Hello ().

Тепер можна відкрити термінал і запустити програму:

Після того, як ви це зробите, в терміналі буде виведено наступне:

Тепер поговоримо про те, як використовувати змінні, які оголошуються в пакетах. Для цього додамо оголошення змінної в файл greet.go:

Відкрийте файл main.go і додайте в нього рядок, в якому функція fmt.Println () використовується для виведення значення змінної Shark, оголошеної в пакеті greet.go. А саме, приведіть main.go до наступного вигляду:

Знову запустіть програму:

Тепер вона виведе наступне:

А зараз поговоримо про те, як оголошувати в пакетах типи. Створимо тип Octopus з полями Name і Color, а також створимо метод типу. Цей метод, за його викликом, буде повертати особливим чином оброблений вміст полів типу Octopus. Доведемо greet.go до наступного вигляду:

Тепер відкрийте main.go, створіть в ньому екземпляр структури нового типу і зверніться до його методу String ():

Після того, як ви, за допомогою конструкції, яка виглядає як oct: = greet.Octopus, створили екземпляр Octopus, ви можете звертатися до методів і властивостей типу із простору імен файлу main.go. Це, зокрема, дозволяє скористатися командою oct.String (), розташованою в кінці файлу main.go, не звертаючись до greet. Крім того, ми можемо, наприклад, звернутися до поля структури Color, скориставшись конструкцією oct.Color. При цьому ми, як і тоді, коли викликали метод, не звертаємося до greet.

Метод String типу Octopus використовує функцію fmt.Sprintf для формування пропозиції і повертає, за допомогою return, результат, рядок, у місце виклику методу (в даному випадку це місце знаходиться в main.go).

Запустимо програму знову:

Вона виведе в консоль наступне:

Тепер, коли ми оснастили Octopus методом String, ми отримали механізм виведення відомостей про тип, відповідний для багаторазового використання. Якщо в майбутньому знадобиться змінити поведінку цього методу, який може використовуватися в багатьох проектах, досить буде один раз відредагувати його код в greet.go.

Експорт сутностей

Можливо, ви звернули увагу на те, що все, з чим ми працювали, звертаючись до пакету greet, має імена, що починаються з великої літери. У Go немає модифікаторів доступу на зразок public, private або protected, які є в інших мовах. Видимість сутностей для зовнішніх механізмів контролюється тим, з якої літери, з маленької або з великої, починаються їхні імена. В результаті типи, змінні, функції, імена яких починаються з великої літери, доступні за межами поточного пакету. Код, який видно за межами пакету, називається експортованим.

Якщо оснастити тип Octopus новим методом з ім’ям reset, то цей метод можна буде викликати з пакету greet, але не з файлу main.go, який знаходиться за межами пакету greet. Ось оновлений варіант greet.go:

Спробуємо викликати reset з файлу main.go:

Це призведе до появи наступної помилки компіляції:

Для того щоб експортувати метод reset типу Octopus потрібно його перейменувати, замінивши першу букву, малу r, на прописну R. Зробимо це, відредагувавши greet.go:

Це призведе до того, що ми зможемо викликати Reset з інших пакетів і при цьому не мати справу з повідомленнями про помилки:

Запустимо програму:

Ось що потрапить в консоль:

Викликавши метод Reset, ми очистили поля Name і Color нашого екземпляра Octopus. В результаті, при виклику String, там, де раніше виводився вміст полів Name і Color, тепер не виводиться нічого.

Підсумки

Написання пакетів Go нічим не відрізняється від написання звичайного Go-коду. Однак розміщення коду пакетів у власних директоріях дозволяє ізолювати код, яким можна скористатися в будь-яких інших Go-проектах. Тут показали те, як оголошувати в пакетах функції, змінні і типи, був розглянутий порядок використання цих сутностей за межами пакетів, розказали, де потрібно зберігати пакети, розраховані на їх багаторазове використання.

Джерело: habr.com

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*