После изучения данного урока вы сможете:

  • Создавать методы для структурированных данных;
  • Применять на практике принципы объектно-ориентированного дизайна.

Go не похож на классические языки программирования. В нем нет классов и объектов, он также не использует наследование. Однако Go по-прежнему предоставляет инструменты для внедрения идей объектно-ориентированного программирования. В данном уроке будет рассмотрена комбинация структур и методов.

Форум Гоферов

Мы работаем над форумом для программистов на Golang. Очень нужны модераторы которые хотят помочь с ответами для новичков и помочь в развитии Go-сообщества.

Go на Форум

Уроки, статьи и Видео

Мы публикуем в паблике ВК и Telegram качественные обучающие материалы для быстрого изучения Go. Подпишитесь на нас в ВК и в Telegram. Поддержите сообщество Go программистов.

Go в ВК Go в Telegram

Содержание статьи

Синергия — модное слово, широко распространенное в предпринимательских кругах. Оно означает «больше, чем сумма всех частей». В языке Go есть типы, методы и структуры. Вместе они более функциональны, нежели классы других языков. Плюс ко всему отпадает необходимость ввода в язык новой концепции.

Какие другие аспекты Go обладают свойством объединения для создания чего-то большего?

Прикрепление методов к структурам в Golang

В уроке о методах мы прикрепляли методы celsius и fahrenheit к типу kelvin для конвертации температур. Методы можно прикрепить к любому объявленному типу. Это работает одинаково, будь-то базовым типом float64 или struct.

Для начала нам нужно объявить тип. В следующем пример объявляется структура coordinate:

Координаты Кратера Брэдбери 4°35’22.2” S, 137°26’30.1” E в формате DMS, или ГМС (градусы, минуты, секунды). В одной минуте 60 секунд («), в одном градусе 60 минут (‘), но в данном случае минуты и секунды указывают на место, а не на время.

Метод decimal в следующем примере конвертирует координаты DMS в градусы с десятичными значениями:

Теперь можно предоставить координаты в удобном формате DMS и конвертировать их в десятичные градусы для совершения вычислений:

Вопрос для проверки:

Что является приемником для десятичного метода в Листинге 2?

Функции конструктора в Golang

Для создания локации в десятичных градусах из градусов, минут и секунд можно использовать метод decimal из Листинга 2 с композитным литералом:

В случае необходимости композитного литерала, что более, чем просто список значений, подумайте о создании функции конструктора. В следующем примере объявляется функция конструктора под названием newLocation.

В классических языках есть конструкторы в виде специальных инструментов для создания объектов. В Python есть __init__(), в Ruby — initialize, а в PHP — __construct(). В Go нет языковых инструментов для конструкторов. Здесь newLocation является обычной функцией с названием, что соответствует правилам именования конструктора.

Функции в форме newType или NewType используются для создания значения указанного типа. Выбор названия newLocation или NewLocation зависит от того, экспортируется ли функция из других пакетов, как было описано в уроке о функциях. newLocation применяется как и любая другая функция.

Если вы хотите создать локации из различных входных данных, просто объявите несколько функций с подходящими названиями — возможно, newLocationDMS и newLocationDD для градусов, минут, секунд и десятичных градусов соответственно.

На заметку: Иногда функции конструктора называют New, как в случае с функцией New из пакета errors. Это все оттого, что в вызовах функции ставится префикс пакета, к которому она относится. Название NewError читалось бы как errors.NewError, а не как более краткий и предпочтительный вариант errors.New.

Вопрос для проверки:

Как можно назвать функцию для создания переменной типа Universe?

Классы в Golang

В Go нет понятия class, как в других популярных языках программирования вроде Python, Ruby или Java. Однако структуры в сочетании с несколькими методами можно использовать для тех же целей. Они не так уж сильно отличаются.

Для создания точки координат для возвращения домой, мы с нуля напишем новый тип world. У него будет поле для радиуса планеты, что будет использовано для вычисления расстояния между двумя локациями, как показано в следующем примере.

Средний объемный радиус Марса составляет 3389,5 км. Вместо объявления 3389,5 как константы, используйте тип world, чтобы объявить Марс одним из многих возможных миров:

Затем метод distance прикрепляется к типу world, давая доступ к полю radius. Он принимает два параметра, оба типа location, и возвращает расстояние в километрах:

Мы будем использовать математические вычисления, для этого нужно импортировать пакет math, что делается следующим образом:

Тип location использует градусы для широты и долготы, однако математические функции стандартной библиотеки использует радианы. Учитывая, что у круга 360° или 2π, следующая функция потребуется для конвертации:

Теперь займемся вычислением расстояния. Используем несколько тригонометрических функций, включая функции для синуса, косинуса и арккосинуса. Если вы увлекаетесь математикой, можете самостоятельно найти формулы, а также вспомнить Сферическую теорему косинусов, чтобы лучше понимать, как работает программа. Марс не является идеальной сферой, но все-таки используем следующую формулу, что позволит добиться приблизительного значения:

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

К слову о результатах. Чтобы посмотреть на distance в действии, объявите несколько локаций и используйте переменную mars, объявленную ранее:

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

Метод distance был взят из формул для Земли, но используется радиус Марса. Объявляя distance как метода типа world, вы можете вычислить расстояние для других миров, к примеру, Земли. Радиус для каждой планеты можете найти в Таблице 2. Данные взяты из Планетарного информационного бюллетеня.

Вопрос для проверки:

В чем преимущество объявления метода distance для типа world по сравнению с менее объектно-ориентированным подходом?

Заключение

  • Сочетание методов и структур предоставляет возможности классических языков программирования без необходимости ввода новых языковых аспектов;
  • Функции конструктора являются обыкновенными функциями.

Итоговое задание для проверки #1:

Используя Листинги 1, 2 и 3, напишите программу, что объявляет location для каждой локации из Таблицы 1. Код должен выводить каждую локацию в десятичных градусах.

oop golang

Итоговое задание для проверки #2:

Используйте метод distance из Листинга 4 и напишите программу, что определяет расстояние между каждой парой мест посадки из Таблицы 1.

  1. Какие места посадки находятся ближе всего друг к другу?
  2. Какие места дальше всего друг от друга?

Для определения расстояния между следующими местами вам понадобиться объявить другие миры, основываясь на данных из Таблицы 2:

  • Найдите расстояние от Лондона, Англия (London, England, 51°30’N 0°08’W) до Парижа, Франция (Paris, France, 48°51’N 2°21’E);
  • Найдите расстояние от вашего города до столицы вашей страны;
  • Найдите расстояние между точками Mount Sharp (5°4’ 48”S, 137°51’E) и Olympus Mons (18°39’N, 226°12’E) на Марсе.

oop go

Понравилась статья?

Поддержи наш проект, чтобы мы могли создать больше хорошего контента!