Image

Category:

GoLang: Семантика типов в Go, что выбирать при объявлении типа и что использовать?

Нельзя было обойти вниманием эту статью "Design Philosophy On Data And Semantics" от Ardan Labs (06-2017)
https://www.ardanlabs.com/blog/2017/06/design-philosophy-on-data-and-semantics.html

Разработчиков всегда мучают вопросы "Как это назвать в коде?", а еще мы по разному создаем типы и используем их. Часто у каждого разработчика свое видение, однако на большой кодовой базе это приводит к разнообразию стилей и ухудшению восприятия кода.

Осмысленное создание и использование типов

  • Уже во время объявления типа решите какую семантику будете использовать при работе с ним (значиние или указатель)

  • Функции и методы должны уважать выбранную семантику типа

  • Избегай наличия ресиверов методов, использующих семантику отличную от соответствующего типа

  • Избегай наличия функций, которые принимают/возвращают данные используя семантику отличную от семантики используемых типов

  • Избегай изменения семанитки для типа

Есть немного исключений из этих рекомендаций, определенно самое заметное - это десериализация (unmarshaling), она всегда требует семантики указателей. Сериализация и десериализация, кажется, всегда будут исключениями из правил.

Несколько конкретных примеров

Встроенные типы

Числовые, булевы, текстовые - по значению. Не используейте указатели на них, чтобы разделять значения пока у вас нет серьезной причины.
Пример из пакета strings:
func Replace(s, old, new string, n int) string

Ссылочные типы

slice, map, interface, function, channel - это ссылочные типы, скрывющие в своей реализации указатели. Их следует передавать по значнию, так как они были спроектированы, чтобы оставаться в стеке и снизить нагрузку на кучу (heap).

Пользовательские типы

Тут вы должны принимать решения сами, как написано выше.

Больше примеров в статье