Нельзя было обойти вниманием эту статью "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).
Пользовательские типы
Тут вы должны принимать решения сами, как написано выше.
Больше примеров в
статье