summaryrefslogtreecommitdiff
path: root/content/pages/gostyleguide/google
diff options
context:
space:
mode:
author2026-02-02 18:57:20 +0300
committer2026-02-02 18:57:20 +0300
commit6c4cbf8578d8a94964ca7327a7826c7c094f94fc (patch)
tree07c5dc52358b5725805a465310bbdfa1f4da82bb /content/pages/gostyleguide/google
parentБольшая чистка блога (diff)
downloadblog-6c4cbf8578d8a94964ca7327a7826c7c094f94fc.tar.gz
blog-6c4cbf8578d8a94964ca7327a7826c7c094f94fc.tar.bz2
blog-6c4cbf8578d8a94964ca7327a7826c7c094f94fc.tar.xz
blog-6c4cbf8578d8a94964ca7327a7826c7c094f94fc.zip
Fix images
Diffstat (limited to 'content/pages/gostyleguide/google')
-rw-r--r--content/pages/gostyleguide/google/_index.md179
-rw-r--r--content/pages/gostyleguide/google/best-practices.md863
-rw-r--r--content/pages/gostyleguide/google/decisions.md800
-rw-r--r--content/pages/gostyleguide/google/guide.md141
-rw-r--r--content/pages/gostyleguide/google/main.md184
5 files changed, 1035 insertions, 1132 deletions
diff --git a/content/pages/gostyleguide/google/_index.md b/content/pages/gostyleguide/google/_index.md
index f28cb04..f773eb9 100644
--- a/content/pages/gostyleguide/google/_index.md
+++ b/content/pages/gostyleguide/google/_index.md
@@ -1,5 +1,4 @@
---
-order: 4
title: Google Go Style Guide
---
@@ -8,3 +7,181 @@ title: Google Go Style Guide
Оригинал: https://google.github.io/styleguide/go
<!--more-->
+
+<!--more -->
+
+Руководство по стилю Go и сопутствующие документы кодифицируют современные
+наилучшие подходы к написанию читаемого и идиоматичного кода на Go. Следование
+Руководству по стилю не является абсолютным требованием, и эти документы никогда
+не будут исчерпывающими. Наша цель — минимизировать неопределённость при
+написании читаемого кода на Go, чтобы новички в языке могли избежать
+распространённых ошибок. Руководство по стилю также служит для унификации
+рекомендаций по стилю, даваемых любым рецензентом кода Go в Google.
+
+| Документ | [Нормативный] | [Канонический] |
+| ----------------------------------------------------------------- | ------------- | -------------- |
+| [**Руководство по стилю**](/pages/gostyleguide/google/guide/) | Да | Да |
+| [**Решения по стилю**](/pages/gostyleguide/google/decisions/) | Да | Нет |
+| [**Лучшие практики**](/pages/gostyleguide/google/best-practices/) | Нет | Нет |
+
+[Нормативный]: #нормативный
+[Канонический]: #канонический
+
+<a id="docs"></a>
+
+### Документы
+
+1. **[Руководство по стилю](/pages/gostyleguide/google/guide)**
+ описывает основы стиля Go в Google. Этот документ является окончательным и
+ служит основой для рекомендаций в «Решениях по стилю» и «Лучших практиках».
+
+1. **[Решения по стилю](/pages/gostyleguide/google/decisions)** —
+ это более подробный документ, который суммирует решения по конкретным
+ вопросам стиля и, где уместно, обсуждает обоснование этих решений.
+
+ Эти решения могут иногда меняться на основе новых данных, новых возможностей
+ языка, новых библиотек или возникающих паттернов, но не ожидается, что
+ отдельные программисты Go в Google должны следить за актуальностью этого
+ документа.
+
+1. **[Лучшие практики](/pages/gostyleguide/google/best-practices)**
+ документируют некоторые паттерны, которые развивались со временем для
+ решения общих задач, хорошо читаются и устойчивы к потребностям поддержки
+ кода.
+
+ Эти лучшие практики не являются каноническими, но программистам Go в Google
+ рекомендуется использовать их там, где это возможно, для сохранения
+ единообразия и согласованности кодовой базы.
+
+Эти документы призваны:
+
+- Согласовать набор принципов для оценки альтернативных стилей
+- Кодифицировать устоявшиеся вопросы стиля Go
+- Документировать и предоставить канонические примеры идиом Go
+- Документировать плюсы и минусы различных решений по стилю
+- Помочь минимизировать неожиданности при рецензировании читаемости кода Go
+- Помочь наставникам по читаемости использовать согласованную терминологию и
+ рекомендации
+
+Эти документы **не** призваны:
+
+- Быть исчерпывающим списком замечаний, которые можно дать при рецензировании
+ читаемости
+- Перечислять все правила, которые каждый должен помнить и всегда соблюдать
+- Заменять здравый смысл при использовании возможностей языка и стиля
+- Оправдывать масштабные изменения для устранения различий в стиле
+
+Всегда будут существовать различия между разными программистами Go и между
+кодовыми базами разных команд. Однако в интересах Google и Alphabet, чтобы наша
+кодовая база была как можно более согласованной. (Подробнее о согласованности
+см. [руководство](https://neonxp.ru/pages/gostyleguide/google/guide/#consistency)). В связи с этим не стесняйтесь вносить
+улучшения стиля по мере необходимости, но вам не нужно придираться к каждому
+нарушению Руководства по стилю, которое вы обнаружите. В частности, эти
+документы могут меняться со временем, и это не повод вызывать лишнюю суету в
+существующих кодовых базах; достаточно писать новый код, используя новейшие
+лучшие практики, и со временем устранять проблемы поблизости.
+
+Важно понимать, что вопросы стиля по своей природе субъективны и всегда
+сопряжены с компромиссами. Большая часть рекомендаций в этих документах
+субъективна, но, как и в случае с `gofmt`, в обеспечиваемом ими единообразии
+есть значительная ценность. Поэтому рекомендации по стилю не будут меняться без
+должного обсуждения, и программистам Go в Google рекомендуется следовать
+руководству по стилю, даже если они с чем-то не согласны.
+
+<a id="definitions"></a>
+
+## Определения
+
+Ниже приведены определения следующих слов, которые используются во всех
+документах по стилю:
+
+- **Канонический**: Устанавливает предписывающие и долговечные правила <a
+ id="canonical"></a>
+
+ В этих документах «канонический» используется для описания чего-либо, что
+ считается стандартом, которому должен следовать весь код (старый и новый) и
+ который не должен существенно меняться с течением времени. Принципы в
+ канонических документах должны быть понятны как авторам, так и рецензентам,
+ поэтому всё, что включается в канонический документ, должно соответствовать
+ высоким стандартам. Как таковые, канонические документы обычно короче и
+ предписывают меньше элементов стиля, чем неканонические документы.
+
+ https://google.github.io/styleguide/go#canonical
+
+- **Нормативный**: Призван установить согласованность <a id="normative"></a>
+
+ В этих документах «нормативный» используется для описания чего-либо, что
+ является согласованным элементом стиля для использования рецензентами кода
+ Go, чтобы предложения, терминология и обоснования были последовательными.
+ Эти элементы могут меняться со временем, и эти документы будут отражать
+ такие изменения, чтобы рецензенты могли оставаться последовательными и в
+ курсе событий. От авторов кода на Go не ожидается знакомства с нормативными
+ документами, но рецензенты будут часто использовать их в качестве
+ справочного материала при проверке читаемости.
+
+ https://google.github.io/styleguide/go#normative
+
+- **Идиоматичный**: Распространённый и знакомый <a id="idiomatic"></a>
+
+ В этих документах «идиоматичный» используется для обозначения чего-либо, что
+ широко распространено в коде на Go и стало знакомым паттерном, который легко
+ узнать. В целом, идиоматичный паттерн следует предпочитать неидиоматичному,
+ если оба служат одной цели в контексте, поскольку именно это будет наиболее
+ знакомо читателям.
+
+ https://google.github.io/styleguide/go#idiomatic
+
+<a id="references"></a>
+
+## Дополнительные ссылки
+
+Данное руководство предполагает, что читатель знаком с [Effective Go], поскольку
+оно обеспечивает общую основу для кода на Go во всём сообществе Go.
+
+Ниже приведены некоторые дополнительные ресурсы для тех, кто хочет
+самостоятельно изучить стиль Go, и для рецензентов, желающих предоставить в
+своих отзывах дополнительный контекст с ссылками. От участников процесса
+проверки читаемости Go не ожидается знакомства с этими ресурсами, но они могут
+упоминаться в качестве контекста при таких проверках.
+
+[Effective Go]: https://go.dev/doc/effective_go
+
+**Внешние ссылки**
+
+- [Спецификация языка Go](https://go.dev/ref/spec)
+- [Часто задаваемые вопросы по Go](https://go.dev/doc/faq)
+- [Модель памяти Go](https://go.dev/ref/mem)
+- [Структуры данных в Go](https://research.swtch.com/godata)
+- [Интерфейсы в Go](https://research.swtch.com/interfaces)
+- [Поговорки Go](https://go-proverbs.github.io/)
+
+- <a id="gotip"></a> Выпуски Go Tip — следите за обновлениями.
+
+- <a id="unit-testing-practices"></a> Практики модульного тестирования —
+ следите за обновлениями.
+
+**Соответствующие статьи Testing-on-the-Toilet**
+
+- [TotT: Именование идентификаторов][tott-431]
+- [TotT: Тестирование состояния vs. Тестирование взаимодействий][tott-281]
+- [TotT: Эффективное тестирование][tott-324]
+- [TotT: Тестирование, основанное на рисках][tott-329]
+- [TotT: Детекторные тесты считаются вредными][tott-350]
+
+[tott-431]: https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html
+[tott-281]: https://testing.googleblog.com/2013/03/testing-on-toilet-testing-state-vs.html
+[tott-324]: https://testing.googleblog.com/2014/05/testing-on-toilet-effective-testing.html
+[tott-329]: https://testing.googleblog.com/2014/05/testing-on-toilet-risk-driven-testing.html
+[tott-350]: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html
+
+**Дополнительные внешние материалы**
+
+- [Go и догма](https://research.swtch.com/dogma)
+- [Меньше — значит экспоненциально
+ больше](https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html)
+- [Воображение
+ Эсмеральды](https://commandcenter.blogspot.com/2011/12/esmereldas-imagination.html)
+- [Регулярные выражения для синтаксического
+ анализа](https://commandcenter.blogspot.com/2011/08/regular-expressions-in-lexing-and.html)
+- [Стиль Gofmt никому не нравится, но Gofmt нравится
+ всем](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=8m43s) (YouTube)
diff --git a/content/pages/gostyleguide/google/best-practices.md b/content/pages/gostyleguide/google/best-practices.md
index 4fc59b1..f7a42c7 100644
--- a/content/pages/gostyleguide/google/best-practices.md
+++ b/content/pages/gostyleguide/google/best-practices.md
@@ -1,15 +1,12 @@
---
-order: 1
-title: Google Go Style Guide — Лучшие практики
+weight: 30
+title: Лучшие практики
---
# Лучшие практики стиля Go (Go Style Best Practices)
Оригинал: https://google.github.io/styleguide/go/best-practices
-[Обзор](https://neonxp.ru/pages/gostyleguide/google/) | [Руководство](https://neonxp.ru/pages/gostyleguide/google/guide) | [Решения](https://neonxp.ru/pages/gostyleguide/google/decisions) |
-[Лучшие практики](https://neonxp.ru/pages/gostyleguide/google/best-practices)
-
**Примечание:** Это часть серии документов, описывающих [Стиль Go (Go
Style)](https://neonxp.ru/pages/gostyleguide/google/) в Google. Данный документ **не является ни [нормативным
(normative)](https://neonxp.ru/pages/gostyleguide/google/#normative), ни [каноническим (canonical)](https://neonxp.ru/pages/gostyleguide/google/#canonical)**,
@@ -44,14 +41,13 @@ Style)](https://neonxp.ru/pages/gostyleguide/google/) в Google. Данный д
будет прочитано. Рассмотрите следующие рекомендации, чтобы избежать избыточного
[повторения (repetition)](https://neonxp.ru/pages/gostyleguide/google/decisions/#repetition) в месте вызова (call site):
-* Следующее, как правило, можно опустить в именах функций и методов:
-
- * Типы входных и выходных данных (если нет конфликта)
- * Тип получателя (receiver) метода
- * Является ли входной или выходной параметр указателем (pointer)
+- Следующее, как правило, можно опустить в именах функций и методов:
+ - Типы входных и выходных данных (если нет конфликта)
+ - Тип получателя (receiver) метода
+ - Является ли входной или выходной параметр указателем (pointer)
-* Для функций не следует [повторять имя
- пакета](https://neonxp.ru/pages/gostyleguide/google/decisions/#repetitive-with-package).
+- Для функций не следует [повторять имя
+ пакета](https://neonxp.ru/pages/gostyleguide/google/decisions/#repetitive-with-package).
```go
// Плохо:
@@ -67,7 +63,7 @@ Style)](https://neonxp.ru/pages/gostyleguide/google/) в Google. Данный д
func Parse(input string) (*Config, error)
```
-* Для методов не следует повторять имя получателя метода.
+- Для методов не следует повторять имя получателя метода.
```go
// Плохо:
@@ -79,7 +75,7 @@ Style)](https://neonxp.ru/pages/gostyleguide/google/) в Google. Данный д
func (c *Config) WriteTo(w io.Writer) (int64, error)
```
-* Не повторяйте имена переменных, передаваемых в качестве параметров.
+- Не повторяйте имена переменных, передаваемых в качестве параметров.
```go
// Плохо:
@@ -91,7 +87,7 @@ Style)](https://neonxp.ru/pages/gostyleguide/google/) в Google. Данный д
func Override(dest, source *Config) error
```
-* Не повторяйте имена и типы возвращаемых значений.
+- Не повторяйте имена и типы возвращаемых значений.
```go
// Плохо:
@@ -118,8 +114,8 @@ func (c *Config) WriteBinaryTo(w io.Writer) (int64, error)
Существуют и другие общие соглашения при выборе имен для функций и методов:
-* Функции, которые что-то возвращают, получают имена, похожие на
- существительные.
+- Функции, которые что-то возвращают, получают имена, похожие на
+ существительные.
```go
// Хорошо:
@@ -134,15 +130,15 @@ func (c *Config) WriteBinaryTo(w io.Writer) (int64, error)
func (c *Config) GetJobName(key string) (value string, ok bool)
```
-* Функции, которые что-то делают, получают имена, похожие на глаголы.
+- Функции, которые что-то делают, получают имена, похожие на глаголы.
```go
// Хорошо:
func (c *Config) WriteDetail(w io.Writer) (int64, error)
```
-* Идентичные функции, которые отличаются только типами, включают имя типа в
- конце имени.
+- Идентичные функции, которые отличаются только типами, включают имя типа в
+ конце имени.
```go
// Хорошо:
@@ -174,8 +170,7 @@ func (c *Config) WriteBinaryTo(w io.Writer) (int64, error)
образом, если ваш код использует фейки или другой вид тестового дубля.
[именование]: guide#naming
-[тестовые дубли (test doubles)]:
- https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts
+[тестовые дубли (test doubles)]: https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts
Предположим, у вас есть хорошо сфокусированный пакет, предоставляющий
production-код, подобный этому:
@@ -212,7 +207,7 @@ func (s *Service) Charge(c *Card, amount money.Money) error { /* опущено
#### Создание вспомогательных тестовых пакетов (Creating test helper packages)
Предположим, вы хотите создать пакет, содержащий тестовые дубли для другого
-пакета. Воспользуемся `package creditcard` (из примера выше):
+пакета. Воспользуемся `package creditcard` (из примера выше):
Один из подходов — создать новый Go-пакет на основе production-пакета для
тестирования. Безопасный выбор — добавить слово `test` к оригинальному имени
@@ -274,8 +269,8 @@ go_library(
См. также:
-* [Go Tip #42: Authoring a Stub for
- Testing](https://google.github.io/styleguide/go/index.html#gotip)
+- [Go Tip #42: Authoring a Stub for
+ Testing](/pages/gostyleguide/google/index.html#gotip)
<a id="naming-doubles-multiple-behaviors"></a>
@@ -436,8 +431,8 @@ func TestProcessor(t *testing.T) {
### Затенение (Shadowing)
-**Примечание:** Это объяснение использует два неформальных термина, *stomping* и
-*shadowing*. Они не являются официальными концепциями в спецификации языка Go.
+**Примечание:** Это объяснение использует два неформальных термина, _stomping_ и
+_shadowing_. Они не являются официальными концепциями в спецификации языка Go.
Как и во многих языках программирования, в Go есть изменяемые переменные:
присваивание переменной меняет ее значение.
@@ -454,7 +449,7 @@ func abs(i int) int {
При использовании [короткого объявления переменных (short variable
declarations)] с оператором `:=` в некоторых случаях новая переменная не
-создается. Мы можем назвать это *stomping* (затирание). Это допустимо, когда
+создается. Мы можем назвать это _stomping_ (затирание). Это допустимо, когда
исходное значение больше не нужно.
```go
@@ -477,7 +472,7 @@ func (s *Server) innerHandler(ctx context.Context, req *pb.MyRequest) *pb.MyResp
```
Однако будьте осторожны с использованием короткого объявления переменных в новой
-области видимости: это вводит новую переменную. Мы можем назвать это *shadowing*
+области видимости: это вводит новую переменную. Мы можем назвать это _shadowing_
(затенение) исходной переменной. Код после конца блока ссылается на оригинал.
Вот ошибочная попытка условно сократить срок действия (deadline):
@@ -536,8 +531,7 @@ func LongFunction() {
}
```
-[короткого объявления переменных (short variable declarations)]:
- https://go.dev/ref/spec#Short_variable_declarations
+[короткого объявления переменных (short variable declarations)]: https://go.dev/ref/spec#Short_variable_declarations
<a id="util-packages"></a>
@@ -549,7 +543,7 @@ func LongFunction() {
Имена пакетов Go должны быть [связаны с тем, что предоставляет
пакет](https://neonxp.ru/pages/gostyleguide/google/decisions/#package-names). Называть пакет просто `util`, `helper`,
`common` или подобным обычно плохой выбор (хотя это может быть использовано как
-*часть* имени). Неинформативные имена затрудняют чтение кода, и если они
+_часть_ имени). Неинформативные имена затрудняют чтение кода, и если они
используются слишком широко, они могут вызывать ненужные [конфликты
импорта](https://neonxp.ru/pages/gostyleguide/google/decisions/#import-renaming).
@@ -592,12 +586,12 @@ b := helper.Marshal(curve, x, y)
Пользователи видят [godoc] для пакета на одной странице, и любые
экспортированные методы типов, предоставляемых пакетом, группируются по их типу.
Godoc также группирует конструкторы вместе с типами, которые они возвращают.
-Если *клиентскому коду* (client code) вероятно потребуется, чтобы два значения
+Если _клиентскому коду_ (client code) вероятно потребуется, чтобы два значения
разных типов взаимодействовали друг с другом, может быть удобно для пользователя
иметь их в одном пакете.
Код внутри пакета имеет доступ к неэкспортированным идентификаторам пакета. Если
-у вас есть несколько связанных типов, *реализация* которых тесно связана,
+у вас есть несколько связанных типов, _реализация_ которых тесно связана,
размещение их в одном пакете позволяет достичь этой связи без загрязнения
публичного API этими деталями. Хороший тест для этой связи — представить
гипотетического пользователя двух пакетов, где пакеты охватывают тесно связанные
@@ -611,7 +605,7 @@ Godoc также группирует конструкторы вместе с
предоставление ему собственного небольшого пакета может облегчить его
использование. Короткое имя пакета, известное клиентам, вместе с именем
экспортированного типа работают вместе, чтобы создать значимый идентификатор:
-например, `bytes.Buffer`, `ring.New`. [Пост об именах пакетов][blog-pkg-names]
+например, `bytes.Buffer`, `ring.New`. [Пост об именах пакетов][blog-pkg-names]
содержит больше примеров.
Стиль Go гибок относительно размера файлов, потому что сопровождающие могут
@@ -637,64 +631,54 @@ Godoc также группирует конструкторы вместе с
Несколько неканонических справочных примеров, чтобы помочь продемонстрировать
эти идеи на практике:
-* маленькие пакеты, содержащие одну связную идею, которая не требует
- добавления или удаления чего-либо еще:
-
- * [пакет `csv`][package `csv`]: кодирование и декодирование данных CSV с
- разделением ответственности соответственно между [reader.go] и
- [writer.go].
- * [пакет `expvar`][package `expvar`]: "белый ящик" (whitebox) телеметрии
- программы, полностью содержащийся в [expvar.go].
-
-* пакеты умеренного размера, содержащие одну большую предметную область и
- несколько связанных с ней ответственностей:
-
- * [пакет `flag`][package `flag`]: управление флагами командной строки,
- полностью содержащееся в [flag.go].
-
-* большие пакеты, которые разделяют несколько тесно связанных предметных
- областей по нескольким файлам:
-
- * [пакет `http`][package `http`]: ядро HTTP: [client.go][http-client],
- поддержка HTTP-клиентов; [server.go][http-server], поддержка
- HTTP-серверов; [cookie.go], управление куками.
- * [пакет `os`][package `os`]: кроссплатформенные абстракции операционной
- системы: [exec.go], управление подпроцессами; [file.go], управление
- файлами; [tempfile.go], временные файлы.
+- маленькие пакеты, содержащие одну связную идею, которая не требует
+ добавления или удаления чего-либо еще:
+ - [пакет `csv`][package `csv`]: кодирование и декодирование данных CSV с
+ разделением ответственности соответственно между [reader.go] и
+ [writer.go].
+ - [пакет `expvar`][package `expvar`]: "белый ящик" (whitebox) телеметрии
+ программы, полностью содержащийся в [expvar.go].
+
+- пакеты умеренного размера, содержащие одну большую предметную область и
+ несколько связанных с ней ответственностей:
+ - [пакет `flag`][package `flag`]: управление флагами командной строки,
+ полностью содержащееся в [flag.go].
+
+- большие пакеты, которые разделяют несколько тесно связанных предметных
+ областей по нескольким файлам:
+ - [пакет `http`][package `http`]: ядро HTTP: [client.go][http-client],
+ поддержка HTTP-клиентов; [server.go][http-server], поддержка
+ HTTP-серверов; [cookie.go], управление куками.
+ - [пакет `os`][package `os`]: кроссплатформенные абстракции операционной
+ системы: [exec.go], управление подпроцессами; [file.go], управление
+ файлами; [tempfile.go], временные файлы.
См. также:
-* [Пакеты тестовых дублей (Test double packages)](#naming-doubles)
-* [Organizing Go Code (Blog Post)]
-* [Organizing Go Code (Presentation)]
+- [Пакеты тестовых дублей (Test double packages)](#naming-doubles)
+- [Organizing Go Code (Blog Post)]
+- [Organizing Go Code (Presentation)]
[blog-pkg-names]: https://go.dev/blog/package-names
[пакет `bytes`]: https://go.dev/src/bytes/
[Organizing Go Code (Blog Post)]: https://go.dev/blog/organizing-go-code
[Organizing Go Code (Presentation)]: https://go.dev/talks/2014/organizeio.slide
[пакет `csv`]: https://pkg.go.dev/encoding/csv
-[reader.go]:
- https://go.googlesource.com/go/+/refs/heads/master/src/encoding/csv/reader.go
-[writer.go]:
- https://go.googlesource.com/go/+/refs/heads/master/src/encoding/csv/writer.go
+[reader.go]: https://go.googlesource.com/go/+/refs/heads/master/src/encoding/csv/reader.go
+[writer.go]: https://go.googlesource.com/go/+/refs/heads/master/src/encoding/csv/writer.go
[пакет `expvar`]: https://pkg.go.dev/expvar
-[expvar.go]:
- https://go.googlesource.com/go/+/refs/heads/master/src/expvar/expvar.go
+[expvar.go]: https://go.googlesource.com/go/+/refs/heads/master/src/expvar/expvar.go
[пакет `flag`]: https://pkg.go.dev/flag
[flag.go]: https://go.googlesource.com/go/+/refs/heads/master/src/flag/flag.go
[godoc]: https://pkg.go.dev/
[пакет `http`]: https://pkg.go.dev/net/http
-[http-client]:
- https://go.googlesource.com/go/+/refs/heads/master/src/net/http/client.go
-[http-server]:
- https://go.googlesource.com/go/+/refs/heads/master/src/net/http/server.go
-[cookie.go]:
- https://go.googlesource.com/go/+/refs/heads/master/src/net/http/cookie.go
+[http-client]: https://go.googlesource.com/go/+/refs/heads/master/src/net/http/client.go
+[http-server]: https://go.googlesource.com/go/+/refs/heads/master/src/net/http/server.go
+[cookie.go]: https://go.googlesource.com/go/+/refs/heads/master/src/net/http/cookie.go
[пакет `os`]: https://pkg.go.dev/os
[exec.go]: https://go.googlesource.com/go/+/refs/heads/master/src/os/exec.go
[file.go]: https://go.googlesource.com/go/+/refs/heads/master/src/os/file.go
-[tempfile.go]:
- https://go.googlesource.com/go/+/refs/heads/master/src/os/tempfile.go
+[tempfile.go]: https://go.googlesource.com/go/+/refs/heads/master/src/os/tempfile.go
<a id="imports"></a>
@@ -708,8 +692,8 @@ Godoc также группирует конструкторы вместе с
их межъязыковой природы. Соглашение для переименованных импортов proto основано
на правиле, которое сгенерировало пакет:
-* Суффикс `pb` обычно используется для правил `go_proto_library`.
-* Суффикс `grpc` обычно используется для правил `go_grpc_library`.
+- Суффикс `pb` обычно используется для правил `go_proto_library`.
+- Суффикс `grpc` обычно используется для правил `go_grpc_library`.
Часто используется одно слово, описывающее пакет:
@@ -722,9 +706,9 @@ import (
```
Следуйте рекомендациям по стилю для [имен
-пакетов](https://google.github.io/styleguide/go/decisions#package-names).
+пакетов](/pages/gostyleguide/google/decisions#package-names).
Предпочитайте целые слова. Короткие имена хороши, но избегайте неоднозначности.
-В случае сомнений используйте имя пакета proto до _go с суффиксом pb:
+В случае сомнений используйте имя пакета proto до \_go с суффиксом pb:
```go
// Хорошо:
@@ -751,9 +735,9 @@ import (
В Go [ошибки — это значения (errors are values)]; они создаются кодом и
потребляются кодом. Ошибки могут быть:
-* Преобразованы в диагностическую информацию для отображения человеку
-* Использованы сопровождающим
-* Интерпретированы конечным пользователем
+- Преобразованы в диагностическую информацию для отображения человеку
+- Использованы сопровождающим
+- Интерпретированы конечным пользователем
Сообщения об ошибках также появляются на самых разных поверхностях, включая
сообщения журнала (log messages), дампы ошибок и отрисованные пользовательские
@@ -766,35 +750,34 @@ import (
тема, и трудно дать категоричные рекомендации. Используйте свое суждение, но
учитывайте следующие соображения:
-* Создавая значение ошибки, решите, придавать ли ему какую-либо
- [структуру](#error-structure).
-* Обрабатывая ошибку, рассмотрите возможность [добавления
- информации](#error-extra-info), которая есть у вас, но которой может не быть
- у вызывающей и/или вызываемой стороны.
-* См. также рекомендации по [логированию ошибок](#error-logging).
+- Создавая значение ошибки, решите, придавать ли ему какую-либо
+ [структуру](#error-structure).
+- Обрабатывая ошибку, рассмотрите возможность [добавления
+ информации](#error-extra-info), которая есть у вас, но которой может не быть
+ у вызывающей и/или вызываемой стороны.
+- См. также рекомендации по [логированию ошибок](#error-logging).
Хотя обычно нецелесообразно игнорировать ошибку, разумным исключением из этого
является оркестрация связанных операций, где часто только первая ошибка полезна.
Пакет [`errgroup`] предоставляет удобную абстракцию для группы операций, которые
могут завершиться ошибкой или быть отменены как группа.
-[ошибки — это значения (errors are values)]:
- https://go.dev/blog/errors-are-values
+[ошибки — это значения (errors are values)]: https://go.dev/blog/errors-are-values
[`errgroup`]: https://pkg.go.dev/golang.org/x/sync/errgroup
См. также:
-* [Effective Go об ошибках](https://go.dev/doc/effective_go#errors)
-* [Пост в блоге Go об ошибках](https://go.dev/blog/go1.13-errors)
-* [Пакет `errors`](https://pkg.go.dev/errors)
-* [Пакет
- `upspin.io/errors`](https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html)
-* [GoTip #89: When to Use Canonical Status Codes as
- Errors](https://google.github.io/styleguide/go/index.html#gotip)
-* [GoTip #48: Error Sentinel
- Values](https://google.github.io/styleguide/go/index.html#gotip)
-* [GoTip #13: Designing Errors for
- Checking](https://google.github.io/styleguide/go/index.html#gotip)
+- [Effective Go об ошибках](https://go.dev/doc/effective_go#errors)
+- [Пост в блоге Go об ошибках](https://go.dev/blog/go1.13-errors)
+- [Пакет `errors`](https://pkg.go.dev/errors)
+- [Пакет
+ `upspin.io/errors`](https://commandcenter.blogspot.com/2017/12/error-handling-in-upspin.html)
+- [GoTip #89: When to Use Canonical Status Codes as
+ Errors](/pages/gostyleguide/google/index.html#gotip)
+- [GoTip #48: Error Sentinel
+ Values](/pages/gostyleguide/google/index.html#gotip)
+- [GoTip #13: Designing Errors for
+ Checking](/pages/gostyleguide/google/index.html#gotip)
<a id="error-structure"></a>
@@ -868,9 +851,9 @@ func handlePet(...) {
}
```
-Не пытайтесь различать ошибки на основе их строковой формы. (См. [GoTip #13:
+Не пытайтесь различать ошибки на основе их строковой формы. (См. [GoTip #13:
Designing Errors for
-Checking](https://google.github.io/styleguide/go/index.html#gotip) для получения
+Checking](/pages/gostyleguide/google/index.html#gotip) для получения
дополнительной информации.)
```go
@@ -891,9 +874,9 @@ func handlePet(...) {
Могут использоваться и другие структуры ошибок, например, структура проекта,
содержащая код ошибки и строку с деталями. [Пакет `status`][status] —
распространенная инкапсуляция; если вы выбираете этот подход (вы не обязаны это
-делать), используйте [канонические коды (canonical codes)]. См. [GoTip #89:
+делать), используйте [канонические коды (canonical codes)]. См. [GoTip #89:
When to Use Canonical Status Codes as
-Errors](https://google.github.io/styleguide/go/index.html#gotip) чтобы понять,
+Errors](/pages/gostyleguide/google/index.html#gotip) чтобы понять,
является ли использование кодов статуса правильным выбором.
[`os.PathError`]: https://pkg.go.dev/os#PathError
@@ -901,8 +884,7 @@ Errors](https://google.github.io/styleguide/go/index.html#gotip) чтобы по
[`errors.As`]: https://pkg.go.dev/errors#As
[`package cmp`]: https://pkg.go.dev/github.com/google/go-cmp/cmp
[status]: https://pkg.go.dev/google.golang.org/grpc/status
-[канонические коды (canonical codes)]:
- https://pkg.go.dev/google.golang.org/grpc/codes
+[канонические коды (canonical codes)]: https://pkg.go.dev/google.golang.org/grpc/codes
<a id="error-extra-info"></a>
@@ -961,21 +943,20 @@ errors)](https://go.dev/blog/go1.13-errors#whether-to-wrap) с помощью
встраивает строковое представление ошибки (то, что возвращает ее метод
`Error()`) в новое значение ошибки, отбрасывая любую структурированную
информацию из исходной ошибки. Примеры использования `%v`:
+ - Добавление интересного, не избыточного контекста: как в примере выше.
- * Добавление интересного, не избыточного контекста: как в примере выше.
-
- * Логирование или отображение ошибок: Когда основная цель — представить
- удобочитаемое сообщение об ошибке в журналах или пользователю, и вы не
- планируете, чтобы вызывающая сторона программно проверяла ошибку с
- помощью `errors.Is` или `errors.As` (Примечание: `errors.Unwrap` здесь,
- как правило, не рекомендуется, так как он не обрабатывает множественные
- ошибки (multi-errors)).
+ - Логирование или отображение ошибок: Когда основная цель — представить
+ удобочитаемое сообщение об ошибке в журналах или пользователю, и вы не
+ планируете, чтобы вызывающая сторона программно проверяла ошибку с
+ помощью `errors.Is` или `errors.As` (Примечание: `errors.Unwrap` здесь,
+ как правило, не рекомендуется, так как он не обрабатывает множественные
+ ошибки (multi-errors)).
- * Создание новых, независимых ошибок: Иногда необходимо преобразовать
- ошибку в новое сообщение об ошибке, тем самым скрывая специфику исходной
- ошибки. Эта практика особенно полезна на границах систем, включая,
- помимо прочего, RPC, IPC и хранилища, где мы переводим
- доменно-специфичные ошибки в каноническое пространство ошибок.
+ - Создание новых, независимых ошибок: Иногда необходимо преобразовать
+ ошибку в новое сообщение об ошибке, тем самым скрывая специфику исходной
+ ошибки. Эта практика особенно полезна на границах систем, включая,
+ помимо прочего, RPC, IPC и хранилища, где мы переводим
+ доменно-специфичные ошибки в каноническое пространство ошибок.
```go
// Хорошо:
@@ -1008,63 +989,63 @@ errors)](https://go.dev/blog/go1.13-errors#whether-to-wrap) с помощью
1. **`%w` (wrap) для программной проверки и цепочки ошибок (error chaining)**
- Глагол `%w` специально предназначен для оборачивания ошибок (error
- wrapping). Он создает новую ошибку, которая предоставляет метод `Unwrap()`,
- позволяя вызывающим сторонам программно проверять цепочку ошибок с помощью
- `errors.Is` и `errors.As`. Примеры использования `%w`:
+ Глагол `%w` специально предназначен для оборачивания ошибок (error
+ wrapping). Он создает новую ошибку, которая предоставляет метод `Unwrap()`,
+ позволяя вызывающим сторонам программно проверять цепочку ошибок с помощью
+ `errors.Is` и `errors.As`. Примеры использования `%w`:
+ - Добавление контекста с сохранением исходной ошибки для программной
+ проверки: Это основной случай использования во вспомогательных функциях
+ (helpers) вашего приложения. Вы хотите обогатить ошибку дополнительным
+ контекстом (например, какая операция выполнялась, когда она завершилась
+ неудачей), но при этом позволить вызывающей стороне проверить, является
+ ли лежащая в основе ошибка конкретной сторожевой ошибкой или типом.
+
+ ```go
+ // Хорошо:
+ func (s *Server) internalFunction(ctx context.Context) error {
+ // ...
+ if err != nil {
+ return fmt.Errorf("couldn't find remote file: %w", err)
+ }
+ }
+ ```
- * Добавление контекста с сохранением исходной ошибки для программной
- проверки: Это основной случай использования во вспомогательных функциях
- (helpers) вашего приложения. Вы хотите обогатить ошибку дополнительным
- контекстом (например, какая операция выполнялась, когда она завершилась
- неудачей), но при этом позволить вызывающей стороне проверить, является
- ли лежащая в основе ошибка конкретной сторожевой ошибкой или типом.
+ Это позволяет функции более высокого уровня выполнить `errors.Is(err,
- ```go
- // Хорошо:
- func (s *Server) internalFunction(ctx context.Context) error {
- // ...
- if err != nil {
- return fmt.Errorf("couldn't find remote file: %w", err)
- }
- }
- ```
+ fs.ErrNotExist)`, даже если исходная ошибка была обернута.
- Это позволяет функции более высокого уровня выполнить `errors.Is(err,
- fs.ErrNotExist)`, даже если исходная ошибка была обернута.
+ В точках, где ваша система взаимодействует с внешними системами, такими
+ как RPC, IPC или хранилище, часто лучше переводить доменно-специфичные
+ ошибки в стандартизированное пространство ошибок (например, коды статуса
+ gRPC), а не просто оборачивать исходную ошибку с помощью `%w`. Клиента
+ обычно не волнует точная внутренняя ошибка файловой системы; их волнует
+ канонический результат (например, `Internal`, `NotFound`,
+ `PermissionDenied`).
- В точках, где ваша система взаимодействует с внешними системами, такими
- как RPC, IPC или хранилище, часто лучше переводить доменно-специфичные
- ошибки в стандартизированное пространство ошибок (например, коды статуса
- gRPC), а не просто оборачивать исходную ошибку с помощью `%w`. Клиента
- обычно не волнует точная внутренняя ошибка файловой системы; их волнует
- канонический результат (например, `Internal`, `NotFound`,
- `PermissionDenied`).
-
- * Когда вы явно документируете и тестируете лежащие в основе ошибки,
- которые вы раскрываете: Если API вашего пакета гарантирует, что
- определенные лежащие в основе ошибки могут быть развернуты и проверены
- вызывающими сторонами (например, "эта функция может вернуть
- `ErrInvalidConfig`, обернутый в более общую ошибку"), то `%w` уместен.
- Это становится частью контракта вашего пакета.
+ - Когда вы явно документируете и тестируете лежащие в основе ошибки,
+ которые вы раскрываете: Если API вашего пакета гарантирует, что
+ определенные лежащие в основе ошибки могут быть развернуты и проверены
+ вызывающими сторонами (например, "эта функция может вернуть
+ `ErrInvalidConfig`, обернутый в более общую ошибку"), то `%w` уместен.
+ Это становится частью контракта вашего пакета.
См. также:
-* [Соглашения по документации ошибок (Error Documentation
- Conventions)](#documentation-conventions-errors)
-* [Пост в блоге об оборачивании ошибок](https://blog.golang.org/go1.13-errors)
+- [Соглашения по документации ошибок (Error Documentation
+ Conventions)](#documentation-conventions-errors)
+- [Пост в блоге об оборачивании ошибок](https://blog.golang.org/go1.13-errors)
<a id="error-percent-w"></a>
### Размещение `%w` в ошибках (Placement of %w in errors)
-Предпочитайте размещать `%w` в конце строки ошибки *если* вы используете
+Предпочитайте размещать `%w` в конце строки ошибки _если_ вы используете
[оборачивание ошибок (error wrapping)](https://go.dev/blog/go1.13-errors) с
глаголом форматирования `%w`.
Ошибки могут быть обернуты с помощью глагола `%w` или путем помещения их в
[структурированную
-ошибку](https://google.github.io/styleguide/go/index.html#gotip), которая
+ошибку](/pages/gostyleguide/google/index.html#gotip), которая
реализует `Unwrap() error` (например,
[`fs.PathError`](https://pkg.go.dev/io/fs#PathError)).
@@ -1133,40 +1114,39 @@ fmt.Println(err3) // err3-1 err2-1 err1 err2-2 err3-2
своим вызывающим сторонам. Логирование — очевидный выбор здесь; но будьте
внимательны к тому, что и как вы логируете.
-* Как и [хорошие сообщения о неудачных тестах (good test failure messages)],
- сообщения журнала должны четко выражать, что пошло не так, и помогать
- сопровождающему, включая соответствующую информацию для диагностики
- проблемы.
+- Как и [хорошие сообщения о неудачных тестах (good test failure messages)],
+ сообщения журнала должны четко выражать, что пошло не так, и помогать
+ сопровождающему, включая соответствующую информацию для диагностики
+ проблемы.
-* Избегайте дублирования. Если вы возвращаете ошибку, обычно лучше не
- логировать ее самостоятельно, а позволить вызывающей стороне обработать ее.
- Вызывающая сторона может выбрать логирование ошибки или, возможно,
- ограничить частоту логирования с помощью [`rate.Sometimes`]. Другие варианты
- включают попытку восстановления или даже [остановку программы]. В любом
- случае, предоставление контроля вызывающей стороне помогает избежать спама в
- журналах.
+- Избегайте дублирования. Если вы возвращаете ошибку, обычно лучше не
+ логировать ее самостоятельно, а позволить вызывающей стороне обработать ее.
+ Вызывающая сторона может выбрать логирование ошибки или, возможно,
+ ограничить частоту логирования с помощью [`rate.Sometimes`]. Другие варианты
+ включают попытку восстановления или даже [остановку программы]. В любом
+ случае, предоставление контроля вызывающей стороне помогает избежать спама в
+ журналах.
Однако обратной стороной этого подхода является то, что любое логирование
записывается с использованием координат строк вызывающей стороны.
-* Будьте осторожны с [PII]. Многие приемники журналов (log sinks) не являются
- подходящими местами назначения для конфиденциальной информации конечных
- пользователей.
+- Будьте осторожны с [PII]. Многие приемники журналов (log sinks) не являются
+ подходящими местами назначения для конфиденциальной информации конечных
+ пользователей.
-* Используйте `log.Error` скупо. Логирование уровня ERROR вызывает сброс
- (flush) и является более дорогостоящим, чем более низкие уровни логирования.
- Это может серьезно повлиять на производительность вашего кода. Принимая
- решение между уровнями error и warning, учитывайте лучшую практику:
- сообщения на уровне error должны быть actionable (то есть требовать
- действий), а не просто "более серьезными", чем warning.
+- Используйте `log.Error` скупо. Логирование уровня ERROR вызывает сброс
+ (flush) и является более дорогостоящим, чем более низкие уровни логирования.
+ Это может серьезно повлиять на производительность вашего кода. Принимая
+ решение между уровнями error и warning, учитывайте лучшую практику:
+ сообщения на уровне error должны быть actionable (то есть требовать
+ действий), а не просто "более серьезными", чем warning.
-* Внутри Google у нас есть системы мониторинга, которые можно настроить для
- более эффективного оповещения, чем просто запись в файл журнала в надежде,
- что кто-то его заметит. Это похоже, но не идентично стандартной библиотеке
- [пакету `expvar`].
+- Внутри Google у нас есть системы мониторинга, которые можно настроить для
+ более эффективного оповещения, чем просто запись в файл журнала в надежде,
+ что кто-то его заметит. Это похоже, но не идентично стандартной библиотеке
+ [пакету `expvar`].
-[хорошие сообщения о неудачных тестах (good test failure messages)]:
- https://google.github.io/styleguide/go/decisions#useful-test-failures
+[хорошие сообщения о неудачных тестах (good test failure messages)]: /pages/gostyleguide/google/decisions#useful-test-failures
[остановку программы]: #checks-and-panics
[`rate.Sometimes`]: https://pkg.go.dev/golang.org/x/time/rate#Sometimes
[PII]: https://en.wikipedia.org/wiki/Personal_data
@@ -1180,9 +1160,9 @@ fmt.Println(err3) // err3-1 err2-1 err1 err2-2 err3-2
может быть полезно для разработки и трассировки. Установление соглашения об
уровнях детализации может быть полезным. Например:
-* Записывайте небольшое количество дополнительной информации на `V(1)`
-* Трассируйте больше информации на `V(2)`
-* Выводите большие внутренние состояния на `V(3)`
+- Записывайте небольшое количество дополнительной информации на `V(1)`
+- Трассируйте больше информации на `V(2)`
+- Выводите большие внутренние состояния на `V(3)`
Чтобы минимизировать стоимость детального логирования, вы должны убедиться, что
случайно не вызываете дорогие функции, даже когда `log.V` выключен. `log.V`
@@ -1251,8 +1231,7 @@ log.V(2).Infof("Handling %v", sql.Explain())
большие трассировки стека, которые остаются необработанными. Избегайте этой
ловушки в своих серверах.
-[решении против паник (decision against panics)]:
- https://google.github.io/styleguide/go/decisions#dont-panic
+[решении против паник (decision against panics)]: /pages/gostyleguide/google/decisions#dont-panic
[`net/http` server]: https://pkg.go.dev/net/http#Server
<a id="when-to-panic"></a>
@@ -1345,14 +1324,13 @@ func answer(i int) string {
См. также:
-* [Handling panics](https://go.dev/ref/spec#Handling_panics) и [Run-time
- Panics](https://go.dev/ref/spec#Run_time_panics) в спецификации языка
-* [Defer, Panic, and Recover](https://go.dev/blog/defer-panic-and-recover)
-* [On the uses and misuses of panics in
- Go](https://eli.thegreenplace.net/2018/on-the-uses-and-misuses-of-panics-in-go/)
+- [Handling panics](https://go.dev/ref/spec#Handling_panics) и [Run-time
+ Panics](https://go.dev/ref/spec#Run_time_panics) в спецификации языка
+- [Defer, Panic, and Recover](https://go.dev/blog/defer-panic-and-recover)
+- [On the uses and misuses of panics in
+ Go](https://eli.thegreenplace.net/2018/on-the-uses-and-misuses-of-panics-in-go/)
-[Go Tip #81: Avoiding Resource Leaks in API Design]:
- https://google.github.io/styleguide/go/index.html#gotip
+[Go Tip #81: Avoiding Resource Leaks in API Design]: /pages/gostyleguide/google/index.html#gotip
<a id="documentation"></a>
@@ -1379,9 +1357,9 @@ func answer(i int) string {
Не каждый параметр должен быть перечислен в документации. Это относится к:
-* параметрам функций и методов
-* полям структур (struct fields)
-* API для опций (options)
+- параметрам функций и методов
+- полям структур (struct fields)
+- API для опций (options)
Документируйте подверженные ошибкам или неочевидные поля и параметры, объясняя,
почему они интересны.
@@ -1419,13 +1397,11 @@ func Sprintf(format string, data ...any) string
См. также:
-* [GoTip #41: Identify Function Call Parameters]
-* [GoTip #51: Patterns for Configuration]
+- [GoTip #41: Identify Function Call Parameters]
+- [GoTip #51: Patterns for Configuration]
-[GoTip #41: Identify Function Call Parameters]:
- https://google.github.io/styleguide/go/index.html#gotip
-[GoTip #51: Patterns for Configuration]:
- https://google.github.io/styleguide/go/index.html#gotip
+[GoTip #41: Identify Function Call Parameters]: /pages/gostyleguide/google/index.html#gotip
+[GoTip #51: Patterns for Configuration]: /pages/gostyleguide/google/index.html#gotip
<a id="documentation-conventions-contexts"></a>
@@ -1456,7 +1432,7 @@ func (Worker) Run(ctx context.Context) error
Когда поведение контекста отличается или неочевидно, его следует прямо
задокументировать, если верно любое из следующего.
-* Функция возвращает ошибку, отличную от `ctx.Err()`, когда контекст отменен:
+- Функция возвращает ошибку, отличную от `ctx.Err()`, когда контекст отменен:
```go
// Хорошо:
@@ -1466,8 +1442,8 @@ func (Worker) Run(ctx context.Context) error
func (Worker) Run(ctx context.Context) error
```
-* Функция имеет другие механизмы, которые могут ее прервать или повлиять на
- время жизни:
+- Функция имеет другие механизмы, которые могут ее прервать или повлиять на
+ время жизни:
```go
// Хорошо:
@@ -1482,8 +1458,8 @@ func (Worker) Run(ctx context.Context) error
func (Worker) Stop()
```
-* Функция имеет особые ожидания относительно времени жизни контекста, его
- происхождения (lineage) или прикрепленных значений (attached values):
+- Функция имеет особые ожидания относительно времени жизни контекста, его
+ происхождения (lineage) или прикрепленных значений (attached values):
```go
// Хорошо:
@@ -1536,7 +1512,7 @@ func (*Buffer) Grow(n int)
Настоятельно рекомендуется документировать, если верно любое из следующего.
-* Непонятно, является ли операция доступной только для чтения или мутирующей:
+- Непонятно, является ли операция доступной только для чтения или мутирующей:
```go
// Хорошо:
@@ -1552,7 +1528,7 @@ func (*Buffer) Grow(n int)
состояние LRU-кэша мутирует. Как это реализовано, может быть неочевидно для
всех читателей.
-* Синхронизация предоставляется API:
+- Синхронизация предоставляется API:
```go
// Хорошо:
@@ -1568,8 +1544,8 @@ func (*Buffer) Grow(n int)
**Примечание:** Если API является типом и API предоставляет синхронизацию в
целом, по соглашению только определение типа документирует семантику.
-* API потребляет пользовательские реализации типов или интерфейсов, и
- потребитель интерфейса имеет особые требования к параллелизму:
+- API потребляет пользовательские реализации типов или интерфейсов, и
+ потребитель интерфейса имеет особые требования к параллелизму:
```go
// Хорошо:
@@ -1632,10 +1608,9 @@ func (c *Client) Get(url string) (resp *Response, err error)
См. также:
-* [GoTip #110: Don’t Mix Exit With Defer]
+- [GoTip #110: Don’t Mix Exit With Defer]
-[GoTip #110: Don’t Mix Exit With Defer]:
- https://google.github.io/styleguide/go/index.html#gotip
+[GoTip #110: Don’t Mix Exit With Defer]: /pages/gostyleguide/google/index.html#gotip
<a id="documentation-conventions-errors"></a>
@@ -1706,10 +1681,10 @@ package os
См. также:
-* [Go Tip #106: Error Naming
- Conventions](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #89: When to Use Canonical Status Codes as
- Errors](https://google.github.io/styleguide/go/index.html#gotip)
+- [Go Tip #106: Error Naming
+ Conventions](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #89: When to Use Canonical Status Codes as
+ Errors](/pages/gostyleguide/google/index.html#gotip)
<a id="documentation-preview"></a>
@@ -1729,7 +1704,7 @@ Go имеет [сервер
[Godoc] предоставляет специальный синтаксис для [форматирования документации].
-* Требуется пустая строка для разделения абзацев:
+- Требуется пустая строка для разделения абзацев:
```go
// Хорошо:
@@ -1738,8 +1713,8 @@ Go имеет [сервер
// См. some/shortlink для подробностей о формате файла конфигурации.
```
-* Файлы тестов могут содержать [запускаемые примеры (runnable examples)],
- которые появляются прикрепленными к соответствующей документации в godoc:
+- Файлы тестов могут содержать [запускаемые примеры (runnable examples)],
+ которые появляются прикрепленными к соответствующей документации в godoc:
```go
// Хорошо:
@@ -1757,8 +1732,8 @@ Go имеет [сервер
}
```
-* Отступ строк на два дополнительных пробела форматирует их буквально
- (verbatim):
+- Отступ строк на два дополнительных пробела форматирует их буквально
+ (verbatim):
```go
// Хорошо:
@@ -1786,9 +1761,9 @@ Go имеет [сервер
// "env" если присутствует, будет заполнен системным окружением.
```
-* Одна строка, которая начинается с заглавной буквы, не содержит знаков
- препинания, кроме скобок и запятых, и за которой следует другой абзац,
- форматируется как заголовок:
+- Одна строка, которая начинается с заглавной буквы, не содержит знаков
+ препинания, кроме скобок и запятых, и за которой следует другой абзац,
+ форматируется как заголовок:
```go
// Хорошо:
@@ -2004,8 +1979,7 @@ var (
)
```
-[составные литералы (composite literal)]:
- https://golang.org/ref/spec#Composite_literals
+[составные литералы (composite literal)]: https://golang.org/ref/spec#Composite_literals
<a id="vardeclsize"></a>
@@ -2039,12 +2013,11 @@ var (
**Предупреждение:** Предварительное выделение больше памяти, чем нужно, может
тратить память в парке (fleet) или даже вредить производительности. В случае
-сомнений см. [GoTip #3: Benchmarking Go Code] и по умолчанию используйте
+сомнений см. [GoTip #3: Benchmarking Go Code] и по умолчанию используйте
[инициализацию нулевым значением](#vardeclzero) или [объявление составным
литералом](#vardeclcomposite).
-[GoTip #3: Benchmarking Go Code]:
- https://google.github.io/styleguide/go/index.html#gotip
+[GoTip #3: Benchmarking Go Code]: /pages/gostyleguide/google/index.html#gotip
<a id="decl-chan"></a>
@@ -2082,8 +2055,7 @@ func sum(values chan int) (out int) {
См. также доклад Брайана Миллса "Rethinking Classical Concurrency Patterns":
[слайды][rethinking-concurrency-slides] [видео][rethinking-concurrency-video].
-[rethinking-concurrency-slides]:
- https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view?usp=sharing
+[rethinking-concurrency-slides]: https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view?usp=sharing
[rethinking-concurrency-video]: https://www.youtube.com/watch?v=5zXAHh5tJqQ
[направление канала (channel direction)]: https://go.dev/ref/spec#Channel_types
@@ -2114,7 +2086,7 @@ API, к которым предъявляются более высокие ст
механизации (least mechanism)].
См. также: [Go Tip #24: Use Case-Specific
-Constructions](https://google.github.io/styleguide/go/index.html#gotip)
+Constructions](/pages/gostyleguide/google/index.html#gotip)
[структуры опций (option struct)]: #option-structure
[вариативных опций (variadic options)]: #variadic-options
@@ -2132,14 +2104,14 @@ Constructions](https://google.github.io/styleguide/go/index.html#gotip)
Использование структуры опций имеет ряд преимуществ:
-* Литерал структуры включает как поля, так и значения для каждого аргумента,
- что делает их самодокументированными и затрудняет их перестановку.
-* Несущественные или "значения по умолчанию" поля могут быть опущены.
-* Вызывающие стороны могут совместно использовать структуру опций и писать
- вспомогательные функции для работы с ней.
-* Структуры обеспечивают более чистую документацию для каждого поля, чем
- аргументы функций.
-* Структуры опций могут расти со временем без влияния на места вызова.
+- Литерал структуры включает как поля, так и значения для каждого аргумента,
+ что делает их самодокументированными и затрудняет их перестановку.
+- Несущественные или "значения по умолчанию" поля могут быть опущены.
+- Вызывающие стороны могут совместно использовать структуру опций и писать
+ вспомогательные функции для работы с ней.
+- Структуры обеспечивают более чистую документацию для каждого поля, чем
+ аргументы функций.
+- Структуры опций могут расти со временем без влияния на места вызова.
Вот пример функции, которую можно улучшить:
@@ -2199,11 +2171,11 @@ func foo(ctx context.Context) {
Этот вариант часто предпочтителен, когда применимо одно из следующих условий:
-* Все вызывающие стороны должны указать одну или несколько опций.
-* Большому количеству вызывающих сторон необходимо предоставить множество
- опций.
-* Опции используются совместно несколькими функциями, которые будет вызывать
- пользователь.
+- Все вызывающие стороны должны указать одну или несколько опций.
+- Большому количеству вызывающих сторон необходимо предоставить множество
+ опций.
+- Опции используются совместно несколькими функциями, которые будет вызывать
+ пользователь.
<a id="variadic-options"></a>
@@ -2215,20 +2187,19 @@ func foo(ctx context.Context) {
опции (если есть), а возвращаемое замыкание принимает изменяемую ссылку (обычно
указатель на тип struct), которая будет обновлена на основе входных данных.
-[вариативный (`...`) параметр]:
- https://golang.org/ref/spec#Passing_arguments_to_..._parameters
+[вариативный (`...`) параметр]: https://golang.org/ref/spec#Passing_arguments_to_..._parameters
Использование вариативных опций может предоставить ряд преимуществ:
-* Опции не занимают места в месте вызова, когда конфигурация не нужна.
-* Опции все еще являются значениями, поэтому вызывающие стороны могут делиться
- ими, писать вспомогательные функции и накапливать их.
-* Опции могут принимать несколько параметров (например,
- `cartesian.Translate(dx, dy int) TransformOption`).
-* Функции опций могут возвращать именованный тип, чтобы группировать опции
- вместе в godoc.
-* Пакеты могут разрешать (или запрещать) сторонним пакетам определять (или
- запрещать определение) свои собственные опции.
+- Опции не занимают места в месте вызова, когда конфигурация не нужна.
+- Опции все еще являются значениями, поэтому вызывающие стороны могут делиться
+ ими, писать вспомогательные функции и накапливать их.
+- Опции могут принимать несколько параметров (например,
+ `cartesian.Translate(dx, dy int) TransformOption`).
+- Функции опций могут возвращать именованный тип, чтобы группировать опции
+ вместе в godoc.
+- Пакеты могут разрешать (или запрещать) сторонним пакетам определять (или
+ запрещать определение) свои собственные опции.
**Примечание:** Использование вариативных опций требует значительного количества
дополнительного кода (см. следующий пример), поэтому их следует использовать
@@ -2327,15 +2298,15 @@ func foo(ctx context.Context) {
Предпочитайте этот вариант, когда применимо большинство из следующего:
-* Большинству вызывающих сторон не нужно указывать никакие опции.
-* Большинство опций используется редко.
-* Существует большое количество опций.
-* Опции требуют аргументов.
-* Опции могут завершиться неудачей или быть установлены неправильно (в этом
- случае функция опции возвращает `error`).
-* Опции требуют большого количества документации, которую трудно уместить в
- структуре.
-* Пользователи или другие пакеты могут предоставлять пользовательские опции.
+- Большинству вызывающих сторон не нужно указывать никакие опции.
+- Большинство опций используется редко.
+- Существует большое количество опций.
+- Опции требуют аргументов.
+- Опции могут завершиться неудачей или быть установлены неправильно (в этом
+ случае функция опции возвращает `error`).
+- Опции требуют большого количества документации, которую трудно уместить в
+ структуре.
+- Пользователи или другие пакеты могут предоставлять пользовательские опции.
Опции в этом стиле должны принимать параметры, а не использовать наличие
(presence) для сигнализации своего значения; последнее может значительно
@@ -2360,10 +2331,8 @@ func foo(ctx context.Context) {
См. [оригинальный пост в блоге Роба Пайка] и [доклад Дейва Ченея] для более
глубокого изучения того, как эти опции могут быть использованы.
-[оригинальный пост в блоге Роба Пайка]:
- http://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
-[доклад Дейва Ченея]:
- https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
+[оригинальный пост в блоге Роба Пайка]: http://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html
+[доклад Дейва Ченея]: https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
<a id="complex-clis"></a>
@@ -2379,18 +2348,16 @@ func foo(ctx context.Context) {
Однако, если вам нужны другие функции, которые она не предоставляет, выберите
один из других вариантов.
-* **[cobra]**
-
- * Соглашение о флагах: getopt
- * Распространена за пределами кодовой базы Google.
- * Много дополнительных функций.
- * Подводные камни в использовании (см. ниже).
-
-* **[subcommands]**
+- **[cobra]**
+ - Соглашение о флагах: getopt
+ - Распространена за пределами кодовой базы Google.
+ - Много дополнительных функций.
+ - Подводные камни в использовании (см. ниже).
- * Соглашение о флагах: Go
- * Проста и с ней легко работать правильно.
- * Рекомендуется, если вам не нужны дополнительные функции.
+- **[subcommands]**
+ - Соглашение о флагах: Go
+ - Проста и с ней легко работать правильно.
+ - Рекомендуется, если вам не нужны дополнительные функции.
**Предупреждение**: функции команд cobra должны использовать `cmd.Context()` для
получения контекста, а не создавать свой собственный корневой контекст с помощью
@@ -2423,17 +2390,17 @@ decisions#mark-test-helpers. Цель не в том, чтобы повторя
Go различает "тестовые помощники (test helpers)" и "помощники утверждений
(assertion helpers)":
-* **Тестовые помощники** — это функции, которые выполняют задачи настройки или
- очистки. Все сбои, которые происходят в тестовых помощниках, ожидаемо
- являются сбоями окружения (а не тестируемого кода) — например, когда
- тестовая база данных не может быть запущена, потому что на этой машине
- больше нет свободных портов. Для таких функций часто уместно вызывать
- `t.Helper`, чтобы [пометить их как тестовый помощник]. См. [обработку ошибок
- в тестовых помощниках] для более подробной информации.
+- **Тестовые помощники** — это функции, которые выполняют задачи настройки или
+ очистки. Все сбои, которые происходят в тестовых помощниках, ожидаемо
+ являются сбоями окружения (а не тестируемого кода) — например, когда
+ тестовая база данных не может быть запущена, потому что на этой машине
+ больше нет свободных портов. Для таких функций часто уместно вызывать
+ `t.Helper`, чтобы [пометить их как тестовый помощник]. См. [обработку ошибок
+ в тестовых помощниках] для более подробной информации.
-* **Помощники утверждений** — это функции, которые проверяют правильность
- системы и завершают тест с ошибкой, если ожидание не выполняется. Помощники
- утверждений [не считаются идиоматичными] в Go.
+- **Помощники утверждений** — это функции, которые проверяют правильность
+ системы и завершают тест с ошибкой, если ожидание не выполняется. Помощники
+ утверждений [не считаются идиоматичными] в Go.
Цель теста — сообщить о условиях прохождения/непрохождения тестируемого кода.
Идеальное место для завершения теста с ошибкой — внутри самой функции `Test`,
@@ -2446,7 +2413,7 @@ Go различает "тестовые помощники (test helpers)" и "
По мере роста вашего тестового кода может стать необходимым вынести некоторую
функциональность в отдельные функции. Стандартные соображения программной
-инженерии все еще применяются, поскольку *тестовый код — это все еще код*. Если
+инженерии все еще применяются, поскольку _тестовый код — это все еще код_. Если
функциональность не взаимодействует с тестовым фреймворком, то применяются все
обычные правила. Однако, когда общий код взаимодействует с фреймворком,
необходимо соблюдать осторожность, чтобы избежать распространенных подводных
@@ -2457,21 +2424,21 @@ Go различает "тестовые помощники (test helpers)" и "
организуйте тест одним из следующих способов вместо использования помощников
утверждений или сложных функций валидации:
-* Встройте логику (и валидацию, и завершение с ошибкой) в функцию `Test`, даже
- если это повторяется. Это лучше всего работает в простых случаях.
-* Если входные данные похожи, рассмотрите возможность объединения их в
- [табличный тест (table-driven test)], сохраняя логику встроенной в цикл. Это
- помогает избежать повторения, сохраняя валидацию и завершение с ошибкой в
- `Test`.
-* Если есть несколько вызывающих сторон, которым нужна одна и та же функция
- валидации, но табличные тесты не подходят (обычно потому, что входные данные
- недостаточно просты или валидация требуется как часть последовательности
- операций), организуйте функцию валидации так, чтобы она возвращала значение
- (обычно `error`), а не принимала параметр `testing.T` и использовала его для
- завершения теста с ошибкой. Используйте логику внутри `Test`, чтобы решить,
- завершать ли тест с ошибкой, и предоставить [полезные сообщения об ошибках
- теста]. Вы также можете создать тестовые помощники для выноса общего
- шаблонного кода настройки.
+- Встройте логику (и валидацию, и завершение с ошибкой) в функцию `Test`, даже
+ если это повторяется. Это лучше всего работает в простых случаях.
+- Если входные данные похожи, рассмотрите возможность объединения их в
+ [табличный тест (table-driven test)], сохраняя логику встроенной в цикл. Это
+ помогает избежать повторения, сохраняя валидацию и завершение с ошибкой в
+ `Test`.
+- Если есть несколько вызывающих сторон, которым нужна одна и та же функция
+ валидации, но табличные тесты не подходят (обычно потому, что входные данные
+ недостаточно просты или валидация требуется как часть последовательности
+ операций), организуйте функцию валидации так, чтобы она возвращала значение
+ (обычно `error`), а не принимала параметр `testing.T` и использовала его для
+ завершения теста с ошибкой. Используйте логику внутри `Test`, чтобы решить,
+ завершать ли тест с ошибкой, и предоставить [полезные сообщения об ошибках
+ теста]. Вы также можете создать тестовые помощники для выноса общего
+ шаблонного кода настройки.
Дизайн, описанный в последнем пункте, сохраняет ортогональность. Например,
[пакет `cmp`] не предназначен для завершения тестов с ошибкой, а для сравнения
@@ -2581,10 +2548,8 @@ type FS interface {
реализацию как черный ящик (blackbox), чтобы убедиться, что она соблюдает самые
основные части контракта `io/fs`.
-[приемочным тестированием (acceptance testing)]:
- https://en.wikipedia.org/wiki/Acceptance_testing
-[инверсии управления (inversion of control)]:
- https://en.wikipedia.org/wiki/Inversion_of_control
+[приемочным тестированием (acceptance testing)]: https://en.wikipedia.org/wiki/Acceptance_testing
+[инверсии управления (inversion of control)]: https://en.wikipedia.org/wiki/Inversion_of_control
[`io/fs`]: https://pkg.go.dev/io/fs
[`testing/fstest`]: https://pkg.go.dev/testing/fstest
[`fstest.TestFS`]: https://pkg.go.dev/testing/fstest#TestFS
@@ -2619,9 +2584,8 @@ type FS interface {
Тест должен отмечать, какие инварианты нарушены и как. Ваш дизайн может
выбрать одну из двух дисциплин для сообщения о сбоях:
-
- * **Завершение при первой ошибке (Fail fast)**: возвращать ошибку, как
- только реализация нарушает инвариант.
+ - **Завершение при первой ошибке (Fail fast)**: возвращать ошибку, как
+ только реализация нарушает инвариант.
Это самый простой подход, и он хорошо работает, если ожидается, что
приемочный тест будет выполняться быстро. Простые [сторожевые ошибки
@@ -2639,8 +2603,8 @@ type FS interface {
}
```
- * **Агрегация всех сбоев (Aggregate all failures)**: собирать все сбои и
- сообщать о них всех.
+ - **Агрегация всех сбоев (Aggregate all failures)**: собирать все сбои и
+ сообщать о них всех.
Этот подход напоминает рекомендацию [продолжать выполнение (keep going)]
и может быть предпочтительнее, если ожидается, что приемочный тест будет
@@ -2712,10 +2676,9 @@ func TestAcceptance(t *testing.T) {
}
```
-[сторожевые ошибки (sentinels)]:
- https://google.github.io/styleguide/go/index.html#gotip
-[пользовательские типы]: https://google.github.io/styleguide/go/index.html#gotip
-[агрегирует ошибки]: https://google.github.io/styleguide/go/index.html#gotip
+[сторожевые ошибки (sentinels)]: /pages/gostyleguide/google/index.html#gotip
+[пользовательские типы]: /pages/gostyleguide/google/index.html#gotip
+[агрегирует ошибки]: /pages/gostyleguide/google/index.html#gotip
<a id="use-real-transports"></a>
@@ -2734,14 +2697,10 @@ func TestAcceptance(t *testing.T) {
double)](https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts)
(например, моку, заглушке или фейку) [OperationsServer].
-[тестовому двойнику (test double)]:
- https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts
-[долго выполняющихся операций (long running operations)]:
- https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning
-[OperationsClient]:
- https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning#OperationsClient
-[OperationsServer]:
- https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning#OperationsServer
+[тестовому двойнику (test double)]: https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts
+[долго выполняющихся операций (long running operations)]: https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning
+[OperationsClient]: https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning#OperationsClient
+[OperationsServer]: https://pkg.go.dev/google.golang.org/genproto/googleapis/longrunning#OperationsServer
Это рекомендуется вместо ручной реализации клиента из-за сложности правильной
имитации поведения клиента. Используя production-клиент с тестовым сервером, вы
@@ -2765,11 +2724,11 @@ double)](https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts)
затрагивают одну запись в таблице теста и делают невозможным продолжение работы
с этой записью, должны сообщаться следующим образом:
-* Если вы не используете подтесты `t.Run`, используйте `t.Error`, за которым
- следует оператор `continue` для перехода к следующей записи таблицы.
-* Если вы используете подтесты (и вы внутри вызова `t.Run`), используйте
- `t.Fatal`, который завершает текущий подтест и позволяет вашему тестовому
- случаю перейти к следующему подтесту.
+- Если вы не используете подтесты `t.Run`, используйте `t.Error`, за которым
+ следует оператор `continue` для перехода к следующей записи таблицы.
+- Если вы используете подтесты (и вы внутри вызова `t.Run`), используйте
+ `t.Fatal`, который завершает текущий подтест и позволяет вашему тестовому
+ случаю перейти к следующему подтесту.
**Предупреждение:** Не всегда безопасно вызывать `t.Fatal` и подобные функции.
[Подробнее здесь](#t-fatal-goroutine).
@@ -2834,8 +2793,8 @@ func addGameAssets(t *testing.T, dir string) error {
**Совет:** Go 1.14 представила функцию [`t.Cleanup`], которую можно использовать
для регистрации функций очистки, которые запускаются при завершении вашего
-теста. Функция также работает с тестовыми помощниками. См. [GoTip #4: Cleaning
-Up Your Tests](https://google.github.io/styleguide/go/index.html#gotip) для
+теста. Функция также работает с тестовыми помощниками. См. [GoTip #4: Cleaning
+Up Your Tests](/pages/gostyleguide/google/index.html#gotip) для
рекомендаций по упрощению тестовых помощников.
Сниппет ниже в вымышленном файле `paint_test.go` демонстрирует, как
@@ -2904,9 +2863,9 @@ FAIL
Правильное использование `(*testing.T).Helper` гораздо лучше определяет
местоположение сбоя, когда:
-* вспомогательные функции растут
-* вспомогательные функции вызывают другие вспомогательные функции
-* количество использований вспомогательных функций в тестовых функциях растет
+- вспомогательные функции растут
+- вспомогательные функции вызывают другие вспомогательные функции
+- количество использований вспомогательных функций в тестовых функциях растет
**Совет:** Если вспомогательная функция вызывает `(*testing.T).Error` или
`(*testing.T).Fatal`, предоставьте некоторый контекст в строке формата, чтобы
@@ -3122,10 +3081,8 @@ testmain]. Это может произойти, если ресурс, треб
[*амортизация общей настройки теста*] или обычного [тестового помощника] для
ваших нужд.
-[пользовательскую точку входа testmain]:
- https://golang.org/pkg/testing/#hdr-Main
-[функциональных тестов (functional tests)]:
- https://en.wikipedia.org/wiki/Functional_testing
+[пользовательскую точку входа testmain]: https://golang.org/pkg/testing/#hdr-Main
+[функциональных тестов (functional tests)]: https://en.wikipedia.org/wiki/Functional_testing
[*амортизация общей настройки теста*]: #t-setup-amortization
[тестового помощника]: #t-common-setup-scope
@@ -3186,9 +3143,9 @@ func TestMain(m *testing.M) {
Использование `sync.Once` может быть уместным, хотя и не обязательно, если все
из следующего верно для общей настройки:
-* Она дорогая.
-* Она применяется только к некоторым тестам.
-* Она не требует очистки.
+- Она дорогая.
+- Она применяется только к некоторым тестам.
+- Она не требует очистки.
```go
// Хорошо:
@@ -3250,11 +3207,11 @@ func TestRegression682831(t *testing.T) {
Есть несколько способов конкатенации строк в Go. Некоторые примеры включают:
-* Оператор "+"
-* `fmt.Sprintf`
-* `strings.Builder`
-* `text/template`
-* `safehtml/template`
+- Оператор "+"
+- `fmt.Sprintf`
+- `strings.Builder`
+- `text/template`
+- `safehtml/template`
Хотя не существует универсального правила, какой выбрать, следующие рекомендации
описывают, когда каждый метод предпочтителен.
@@ -3318,8 +3275,8 @@ for i, d := range digitsOfPi {
str := b.String()
```
-**Примечание:** Для более подробного обсуждения см. [GoTip #29: Building
-Strings Efficiently](https://google.github.io/styleguide/go/index.html#gotip).
+**Примечание:** Для более подробного обсуждения см. [GoTip #29: Building
+Strings Efficiently](/pages/gostyleguide/google/index.html#gotip).
<a id="string-constants"></a>
@@ -3362,8 +3319,7 @@ state)](https://en.wikipedia.org/wiki/Global_variable). Им рекоменду
критично для поставщиков инфраструктуры, которые предлагают библиотеки,
интеграции и сервисы другим командам.
-[глобальное состояние (global state)]:
- https://en.wikipedia.org/wiki/Global_variable
+[глобальное состояние (global state)]: https://en.wikipedia.org/wiki/Global_variable
[уровне пакета (package level)]: https://go.dev/ref/spec#TopLevelDecl
```go
@@ -3402,18 +3358,18 @@ func main() {
См. также:
-* [Go Tip #5: Slimming Your Client
- Libraries](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #24: Use Case-Specific
- Constructions](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #40: Improving Time Testability with Function
- Parameters](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #41: Identify Function Call
- Parameters](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #44: Improving Time Testability with Struct
- Fields](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #80: Dependency Injection
- Principles](https://google.github.io/styleguide/go/index.html#gotip)
+- [Go Tip #5: Slimming Your Client
+ Libraries](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #24: Use Case-Specific
+ Constructions](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #40: Improving Time Testability with Function
+ Parameters](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #41: Identify Function Call
+ Parameters](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #44: Improving Time Testability with Struct
+ Fields](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #80: Dependency Injection
+ Principles](/pages/gostyleguide/google/index.html#gotip)
API, которые не поддерживают явную передачу зависимостей, становятся хрупкими с
увеличением числа клиентов:
@@ -3480,53 +3436,54 @@ func TestRegression_InvalidUser(t *testing.T) {
Использование глобального состояния создает проблемы, на которые нет простых
ответов для вас и клиентов API:
-* Что произойдет, если клиенту нужно использовать разные и отдельно работающие
- наборы `Plugin` (например, для поддержки нескольких серверов) в одном
- процессе?
+- Что произойдет, если клиенту нужно использовать разные и отдельно работающие
+ наборы `Plugin` (например, для поддержки нескольких серверов) в одном
+ процессе?
-* Что произойдет, если клиент захочет заменить зарегистрированный `Plugin`
- альтернативной реализацией в тесте, например, [тестовым двойником]?
+- Что произойдет, если клиент захочет заменить зарегистрированный `Plugin`
+ альтернативной реализацией в тесте, например, [тестовым двойником]?
Что произойдет, если тестам клиента требуется герметичность между
экземплярами `Plugin` или между всеми зарегистрированными плагинами?
-* Что произойдет, если несколько клиентов `Register` плагин `Plugin` под одним
- и тем же именем? Кто победит, если вообще победит?
+- Что произойдет, если несколько клиентов `Register` плагин `Plugin` под одним
+ и тем же именем? Кто победит, если вообще победит?
Как следует [обрабатывать](https://neonxp.ru/pages/gostyleguide/google/decisions/#handle-errors) ошибки? Если код
вызывает panic или `log.Fatal`, будет ли это всегда [уместно для всех мест,
в которых может быть вызван API](https://neonxp.ru/pages/gostyleguide/google/decisions/#dont-panic)? Может ли клиент
проверить, что он не делает ничего плохого, прежде чем сделать это?
-* Существуют ли определенные этапы начальной загрузки программы или ее
- жизненного цикла, во время которых можно вызывать `Register`, а когда нет?
+- Существуют ли определенные этапы начальной загрузки программы или ее
+ жизненного цикла, во время которых можно вызывать `Register`, а когда нет?
+
+ Что произойдет, если `Register` будет вызван в неподходящее время? Клиент
+ может вызвать `Register` в [`func
- Что произойдет, если `Register` будет вызван в неподходящее время? Клиент
- может вызвать `Register` в [`func
init`](https://go.dev/ref/spec#Package_initialization), до разбора флагов
- или после `main`. Этап, на котором вызывается функция, влияет на обработку
- ошибок. Если автор API предполагает, что API вызывается *только* во время
- инициализации программы без требования, чтобы это было так, это
- предположение может подтолкнуть автора к проектированию обработки ошибок для
- [завершения программы](https://neonxp.ru/pages/gostyleguide/google/best-practices/#program-init), моделируя API как
- функцию типа `Must`. Завершение не подходит для библиотечных функций общего
+или после `main`. Этап, на котором вызывается функция, влияет на обработку
+ошибок. Если автор API предполагает, что API вызывается _только_ во время
+инициализации программы без требования, чтобы это было так, это
+предположение может подтолкнуть автора к проектированию обработки ошибок для
+[завершения программы](https://neonxp.ru/pages/gostyleguide/google/best-practices/#program-init), моделируя API как
+функцию типа `Must`. Завершение не подходит для библиотечных функций общего
назначения, которые могут использоваться на любом этапе.
-* Что, если потребности в параллелизме клиента и дизайнера не совпадают?
+- Что, если потребности в параллелизме клиента и дизайнера не совпадают?
См. также:
-* [Go Tip #36: Enclosing Package-Level
- State](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #71: Reducing Parallel Test
- Flakiness](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #80: Dependency Injection
- Principles](https://google.github.io/styleguide/go/index.html#gotip)
-* Обработка ошибок: [Look Before You
- Leap](https://docs.python.org/3/glossary.html#term-LBYL) против [Easier to
- Ask for Forgiveness than
- Permission](https://docs.python.org/3/glossary.html#term-EAFP)
-* [Unit Testing Practices on Public APIs]
+- [Go Tip #36: Enclosing Package-Level
+ State](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #71: Reducing Parallel Test
+ Flakiness](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #80: Dependency Injection
+ Principles](/pages/gostyleguide/google/index.html#gotip)
+- Обработка ошибок: [Look Before You
+ Leap](https://docs.python.org/3/glossary.html#term-LBYL) против [Easier to
+ Ask for Forgiveness than
+ Permission](https://docs.python.org/3/glossary.html#term-EAFP)
+- [Unit Testing Practices on Public APIs]
Глобальное состояние имеет каскадные эффекты на [здоровье кодовой базы
Google](https://neonxp.ru/pages/gostyleguide/google/guide/.md#maintainability). К глобальному состоянию следует подходить с
@@ -3544,7 +3501,7 @@ Google](https://neonxp.ru/pages/gostyleguide/google/guide/.md#maintainability).
Ниже перечислены несколько наиболее распространенных проблемных форм API:
-* Переменные верхнего уровня, независимо от того, экспортируются они или нет.
+- Переменные верхнего уровня, независимо от того, экспортируются они или нет.
```go
// Плохо:
@@ -3558,14 +3515,14 @@ Google](https://neonxp.ru/pages/gostyleguide/google/guide/.md#maintainability).
См. [лакмусовые тесты](#globals-litmus-tests), чтобы узнать, когда они
безопасны.
-* Шаблон [локатора служб (service locator
- pattern)](https://en.wikipedia.org/wiki/Service_locator_pattern). См.
- [первый пример](#globals). Сам шаблон локатора служб не является
- проблематичным, а проблема в том, что локатор определен как глобальный.
+- Шаблон [локатора служб (service locator
+ pattern)](https://en.wikipedia.org/wiki/Service_locator_pattern). См.
+ [первый пример](#globals). Сам шаблон локатора служб не является
+ проблематичным, а проблема в том, что локатор определен как глобальный.
-* Реестры для [обратных вызовов
- (callbacks)](https://en.wikipedia.org/wiki/Callback_\(computer_programming\))
- и подобного поведения.
+- Реестры для [обратных вызовов
+ (callbacks)](<https://en.wikipedia.org/wiki/Callback_(computer_programming)>)
+ и подобного поведения.
```go
// Плохо:
@@ -3578,9 +3535,9 @@ Google](https://neonxp.ru/pages/gostyleguide/google/guide/.md#maintainability).
}
```
-* "Толстые" (thick) клиентские синглтоны для таких вещей, как бэкенды,
- хранилища, уровни доступа к данным и другие системные ресурсы. Они часто
- создают дополнительные проблемы с надежностью служб.
+- "Толстые" (thick) клиентские синглтоны для таких вещей, как бэкенды,
+ хранилища, уровни доступа к данным и другие системные ресурсы. Они часто
+ создают дополнительные проблемы с надежностью служб.
```go
// Плохо:
@@ -3598,7 +3555,7 @@ Google](https://neonxp.ru/pages/gostyleguide/google/guide/.md#maintainability).
> **Примечание:** Многие устаревшие API в кодовой базе Google не следуют этому
> руководству; фактически, некоторые стандартные библиотеки Go позволяют
-> настраивать поведение через глобальные значения. Тем не менее, нарушение
+> настраивать поведение через глобальные значения. Тем не менее, нарушение
> этого руководства устаревшим API **[не должно использоваться как
> прецедент](https://neonxp.ru/pages/gostyleguide/google/guide/#local-consistency)** для продолжения шаблона.
>
@@ -3611,31 +3568,31 @@ Google](https://neonxp.ru/pages/gostyleguide/google/guide/.md#maintainability).
[API, использующие шаблоны выше](#globals-forms), небезопасны, когда:
-* Несколько функций взаимодействуют через глобальное состояние при выполнении
- в одной программе, несмотря на то, что в остальном они независимы (например,
- написаны разными авторами в совершенно разных каталогах).
-* Независимые тестовые случаи взаимодействуют друг с другом через глобальное
- состояние.
-* Пользователи API склонны заменять или подменять глобальное состояние для
- целей тестирования, особенно чтобы заменить любую часть состояния [тестовым
- двойником], например, заглушкой, фейком, шпионом или моком.
-* Пользователи должны учитывать особые требования к порядку при взаимодействии
- с глобальным состоянием: `func init`, разобраны ли уже флаги и т.д.
+- Несколько функций взаимодействуют через глобальное состояние при выполнении
+ в одной программе, несмотря на то, что в остальном они независимы (например,
+ написаны разными авторами в совершенно разных каталогах).
+- Независимые тестовые случаи взаимодействуют друг с другом через глобальное
+ состояние.
+- Пользователи API склонны заменять или подменять глобальное состояние для
+ целей тестирования, особенно чтобы заменить любую часть состояния [тестовым
+ двойником], например, заглушкой, фейком, шпионом или моком.
+- Пользователи должны учитывать особые требования к порядку при взаимодействии
+ с глобальным состоянием: `func init`, разобраны ли уже флаги и т.д.
При условии, что вышеуказанные условия избегаются, существует **несколько
ограниченных обстоятельств, при которых эти API безопасны**, а именно, когда
верно любое из следующего:
-* Глобальное состояние логически постоянно
- ([пример](https://github.com/klauspost/compress/blob/290f4cfacb3eff892555a491e3eeb569a48665e7/zstd/snappy.go#L413)).
-* Наблюдаемое поведение пакета является бессостоятельным (stateless).
- Например, общедоступная функция может использовать частную глобальную
- переменную в качестве кэша, но пока вызывающая сторона не может отличить
- попадания в кэш от промахов, функция является бессостоятельной.
-* Глобальное состояние не просачивается в вещи, внешние по отношению к
- программе, такие как sidecar-процессы или файлы в общей файловой системе.
-* Нет ожидания предсказуемого поведения
- ([пример](https://pkg.go.dev/math/rand)).
+- Глобальное состояние логически постоянно
+ ([пример](https://github.com/klauspost/compress/blob/290f4cfacb3eff892555a491e3eeb569a48665e7/zstd/snappy.go#L413)).
+- Наблюдаемое поведение пакета является бессостоятельным (stateless).
+ Например, общедоступная функция может использовать частную глобальную
+ переменную в качестве кэша, но пока вызывающая сторона не может отличить
+ попадания в кэш от промахов, функция является бессостоятельной.
+- Глобальное состояние не просачивается в вещи, внешние по отношению к
+ программе, такие как sidecar-процессы или файлы в общей файловой системе.
+- Нет ожидания предсказуемого поведения
+ ([пример](https://pkg.go.dev/math/rand)).
> **Примечание:**
> [Sidecar-процессы](https://www.oreilly.com/library/view/designing-distributed-systems/9781491983638/ch02.html)
@@ -3653,18 +3610,18 @@ image`](https://pkg.go.dev/image) с его функцией
лакмусовые тесты, примененные к типичному декодеру, например, для обработки
формата [PNG](https://pkg.go.dev/image/png):
-* Множественные вызовы API `package image`, использующие зарегистрированные
- декодеры (например, `image.Decode`), не могут мешать друг другу, аналогично
- и для тестов. Единственное исключение — `image.RegisterFormat`, но это
- смягчается пунктами ниже.
-* Крайне маловероятно, что пользователь захочет заменить декодер [тестовым
- двойником], так как декодер PNG является примером случая, когда предпочтение
- нашей кодовой базы реальным объектам применяется. Однако пользователь с
- большей вероятностью заменит декодер тестовым двойником, если декодер
- состоятельно взаимодействует с ресурсами операционной системы (например,
- сетью).
-* Коллизии при регистрации возможны, хотя на практике они, вероятно, редки.
-* Декодеры являются бессостоятельными, идемпотентными и чистыми (pure).
+- Множественные вызовы API `package image`, использующие зарегистрированные
+ декодеры (например, `image.Decode`), не могут мешать друг другу, аналогично
+ и для тестов. Единственное исключение — `image.RegisterFormat`, но это
+ смягчается пунктами ниже.
+- Крайне маловероятно, что пользователь захочет заменить декодер [тестовым
+ двойником], так как декодер PNG является примером случая, когда предпочтение
+ нашей кодовой базы реальным объектам применяется. Однако пользователь с
+ большей вероятностью заменит декодер тестовым двойником, если декодер
+ состоятельно взаимодействует с ресурсами операционной системы (например,
+ сетью).
+- Коллизии при регистрации возможны, хотя на практике они, вероятно, редки.
+- Декодеры являются бессостоятельными, идемпотентными и чистыми (pure).
<a id="globals-default-instance"></a>
@@ -3714,14 +3671,12 @@ image`](https://pkg.go.dev/image) с его функцией
состояния к известному хорошему значению по умолчанию (например, для
облегчения тестирования).
-[целями сборки бинарников (binary build targets)]:
- https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_binary
-[библиотеками (libraries)]:
- https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_library
+[целями сборки бинарников (binary build targets)]: https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_binary
+[библиотеками (libraries)]: https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_library
См. также:
-* [Go Tip #36: Enclosing Package-Level
- State](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #80: Dependency Injection
- Principles](https://google.github.io/styleguide/go/index.html#gotip)
+- [Go Tip #36: Enclosing Package-Level
+ State](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #80: Dependency Injection
+ Principles](/pages/gostyleguide/google/index.html#gotip)
diff --git a/content/pages/gostyleguide/google/decisions.md b/content/pages/gostyleguide/google/decisions.md
index acb17b7..adce93d 100644
--- a/content/pages/gostyleguide/google/decisions.md
+++ b/content/pages/gostyleguide/google/decisions.md
@@ -1,16 +1,12 @@
---
-order: 2
-title: Google Go Style Guide — Решения
+weight: 20
+title: Решения
---
# Решения по стилю Go
Оригинал: https://google.github.io/styleguide/go/decisions
-[Обзор](https://neonxp.ru/pages/gostyleguide/google/) | [Руководство](https://neonxp.ru/pages/gostyleguide/google/guide) | [Решения](https://neonxp.ru/pages/gostyleguide/google/decisions) |
-[Лучшие практики](https://neonxp.ru/pages/gostyleguide/google/best-practices)
-
-
**Примечание:** Это часть серии документов, описывающих [Стиль Go](https://neonxp.ru/pages/gostyleguide/google/) в
Google. Этот документ является **[нормативным](https://neonxp.ru/pages/gostyleguide/google/#normative), но не
[каноническим](https://neonxp.ru/pages/gostyleguide/google/#canonical)** и подчиняется [основному руководству по
@@ -35,21 +31,21 @@ Google. Этот документ является **[нормативным](ht
Следующие разделы были перемещены из "Решений по стилю" в другие части
руководства:
-* **MixedCaps**: см. [guide#mixed-caps](https://neonxp.ru/pages/gostyleguide/google/guide/#mixed-caps) <a
- id="mixed-caps"></a>
+- **MixedCaps**: см. [guide#mixed-caps](https://neonxp.ru/pages/gostyleguide/google/guide/#mixed-caps) <a
+ id="mixed-caps"></a>
-* **Форматирование**: см. [guide#formatting](https://neonxp.ru/pages/gostyleguide/google/guide/#formatting) <a
- id="formatting"></a>
+- **Форматирование**: см. [guide#formatting](https://neonxp.ru/pages/gostyleguide/google/guide/#formatting) <a
+ id="formatting"></a>
-* **Длина строки**: см. [guide#line-length](https://neonxp.ru/pages/gostyleguide/google/guide/#line-length) <a
- id="line-length"></a>
+- **Длина строки**: см. [guide#line-length](https://neonxp.ru/pages/gostyleguide/google/guide/#line-length) <a
+ id="line-length"></a>
<a id="naming"></a>
## Именование
Общие рекомендации по именованию см. в разделе об именовании в [основном
-руководстве по стилю](https://neonxp.ru/pages/gostyleguide/google/guide/#naming). Следующие разделы дают дальнейшие
+руководстве по стилю](https://neonxp.ru/pages/gostyleguide/google/guide/#naming). Следующие разделы дают дальнейшие
разъяснения по конкретным областям именования.
<a id="underscores"></a>
@@ -98,18 +94,18 @@ Google. Этот документ является **[нормативным](ht
сгенерированным кодом, могут содержать подчеркивания. Конкретные примеры
включают:
-* Использование суффикса `_test` для модульных тестов, проверяющих только
- экспортированный API пакета (пакет `testing` называет это ["черным
- ящиком"](https://pkg.go.dev/testing)). Например, пакет `linkedlist` должен
- определять свои модульные тесты "черного ящика" в пакете с именем
- `linkedlist_test` (не `linked_list_test`)
+- Использование суффикса `_test` для модульных тестов, проверяющих только
+ экспортированный API пакета (пакет `testing` называет это ["черным
+ ящиком"](https://pkg.go.dev/testing)). Например, пакет `linkedlist` должен
+ определять свои модульные тесты "черного ящика" в пакете с именем
+ `linkedlist_test` (не `linked_list_test`)
-* Использование подчеркиваний и суффикса `_test` для пакетов, содержащих
- функциональные или интеграционные тесты. Например, интеграционный тест
- сервиса связного списка может называться `linked_list_service_test`
+- Использование подчеркиваний и суффикса `_test` для пакетов, содержащих
+ функциональные или интеграционные тесты. Например, интеграционный тест
+ сервиса связного списка может называться `linked_list_service_test`
-* Использование суффикса `_test` для [примеров документации на уровне
- пакета](https://go.dev/blog/examples)
+- Использование суффикса `_test` для [примеров документации на уровне
+ пакета](https://go.dev/blog/examples)
[`tabwriter`]: https://pkg.go.dev/text/tabwriter
[`k8s`]: https://pkg.go.dev/k8s.io/client-go/kubernetes
@@ -120,17 +116,17 @@ Google. Этот документ является **[нормативным](ht
`helper`, `model`, `testhelper` и т.д., которые могут побуждать пользователей
пакета [переименовывать его при импорте](#import-renaming). См.:
-* [Рекомендации по так называемым "служебным
- пакетам"](https://neonxp.ru/pages/gostyleguide/google/best-practices/#util-packages)
-* [Go Tip #97: Что в
- имени](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #108: Сила хорошего имени
- пакета](https://google.github.io/styleguide/go/index.html#gotip)
+- [Рекомендации по так называемым "служебным
+ пакетам"](https://neonxp.ru/pages/gostyleguide/google/best-practices/#util-packages)
+- [Go Tip #97: Что в
+ имени](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #108: Сила хорошего имени
+ пакета](/pages/gostyleguide/google/index.html#gotip)
Когда импортированный пакет переименовывается (например, `import foopb
"path/to/foo_go_proto"`), локальное имя пакета должно соответствовать правилам
выше, так как локальное имя определяет, как на символы в пакете ссылаются в
-файле. Если данный импорт переименован в нескольких файлах, особенно в одном и
+файле. Если данный импорт переименован в нескольких файлах, особенно в одном и
том же или соседних пакетах, по возможности следует использовать одно и то же
локальное имя для согласованности.
@@ -147,16 +143,16 @@ Google. Этот документ является **[нормативным](ht
Имена [получателей] (receiver) должны быть:
-* Краткими (обычно одна или две буквы)
-* Сокращениями для самого типа
-* Применяться последовательно для каждого получателя этого типа
+- Краткими (обычно одна или две буквы)
+- Сокращениями для самого типа
+- Применяться последовательно для каждого получателя этого типа
-Длинное имя | Лучшее имя
------------------------------ | -------------------------
-`func (tray Tray)` | `func (t Tray)`
-`func (info *ResearchInfo)` | `func (ri *ResearchInfo)`
-`func (this *ReportWriter)` | `func (w *ReportWriter)`
-`func (self *Scanner)` | `func (s *Scanner)`
+| Длинное имя | Лучшее имя |
+| --------------------------- | ------------------------- |
+| `func (tray Tray)` | `func (t Tray)` |
+| `func (info *ResearchInfo)` | `func (ri *ResearchInfo)` |
+| `func (this *ReportWriter)` | `func (w *ReportWriter)` |
+| `func (self *Scanner)` | `func (s *Scanner)` |
[получателей]: https://golang.org/ref/spec#Method_declarations
@@ -221,35 +217,34 @@ const (
правило, идентификаторы (например, `ID` и `DB`) также должны быть написаны с
заглавной буквы, аналогично их использованию в английской прозе.
-* В именах с несколькими аббревиатурами (например, `XMLAPI`, потому что оно
- содержит `XML` и `API`) каждая буква в данной аббревиатуре должна иметь один
- регистр, но каждая аббревиатура в имени не обязана иметь одинаковый регистр.
-* В именах с аббревиатурой, содержащей строчную букву (например, `DDoS`,
- `iOS`, `gRPC`), аббревиатура должна отображаться, как в стандартной прозе,
- если только вам не нужно изменить первую букву ради [экспортируемости
- (exportedness)]. В этих случаях вся аббревиатура должна быть в одном
- регистре (например, `ddos`, `IOS`, `GRPC`).
+- В именах с несколькими аббревиатурами (например, `XMLAPI`, потому что оно
+ содержит `XML` и `API`) каждая буква в данной аббревиатуре должна иметь один
+ регистр, но каждая аббревиатура в имени не обязана иметь одинаковый регистр.
+- В именах с аббревиатурой, содержащей строчную букву (например, `DDoS`,
+ `iOS`, `gRPC`), аббревиатура должна отображаться, как в стандартной прозе,
+ если только вам не нужно изменить первую букву ради [экспортируемости
+ (exportedness)]. В этих случаях вся аббревиатура должна быть в одном
+ регистре (например, `ddos`, `IOS`, `GRPC`).
-[экспортируемости (exportedness)]:
- https://golang.org/ref/spec#Exported_identifiers
+[экспортируемости (exportedness)]: https://golang.org/ref/spec#Exported_identifiers
<!-- Keep this table narrow. If it must grow wider, replace with a list. -->
-Использование в английском | Область видимости | Правильно | Неправильно
--------------------------- | ----------------- | --------- | --------------------------------------
-XML API | Экспортировано | `XMLAPI` | `XmlApi`, `XMLApi`, `XmlAPI`, `XMLapi`
-XML API | Не экспортировано | `xmlAPI` | `xmlapi`, `xmlApi`
-iOS | Экспортировано | `IOS` | `Ios`, `IoS`
-iOS | Не экспортировано | `iOS` | `ios`
-gRPC | Экспортировано | `GRPC` | `Grpc`
-gRPC | Не экспортировано | `gRPC` | `grpc`
-DDoS | Экспортировано | `DDoS` | `DDOS`, `Ddos`
-DDoS | Не экспортировано | `ddos` | `dDoS`, `dDOS`
-ID | Экспортировано | `ID` | `Id`
-ID | Не экспортировано | `id` | `iD`
-DB | Экспортировано | `DB` | `Db`
-DB | Не экспортировано | `db` | `dB`
-Txn | Экспортировано | `Txn` | `TXN`
+| Использование в английском | Область видимости | Правильно | Неправильно |
+| -------------------------- | ----------------- | --------- | -------------------------------------- |
+| XML API | Экспортировано | `XMLAPI` | `XmlApi`, `XMLApi`, `XmlAPI`, `XMLapi` |
+| XML API | Не экспортировано | `xmlAPI` | `xmlapi`, `xmlApi` |
+| iOS | Экспортировано | `IOS` | `Ios`, `IoS` |
+| iOS | Не экспортировано | `iOS` | `ios` |
+| gRPC | Экспортировано | `GRPC` | `Grpc` |
+| gRPC | Не экспортировано | `gRPC` | `grpc` |
+| DDoS | Экспортировано | `DDoS` | `DDOS`, `Ddos` |
+| DDoS | Не экспортировано | `ddos` | `dDoS`, `dDOS` |
+| ID | Экспортировано | `ID` | `Id` |
+| ID | Не экспортировано | `id` | `iD` |
+| DB | Экспортировано | `DB` | `Db` |
+| DB | Не экспортировано | `db` | `dB` |
+| Txn | Экспортировано | `Txn` | `TXN` |
<!--#include file="/go/g3doc/style/includes/special-name-exception.md"-->
@@ -289,14 +284,14 @@ Txn | Экспортировано | `Txn` | `TXN`
строгими правилами. Применяйте суждение, основанное на контексте, [ясности] и
[лаконичности].
-* Малая область видимости — это область, в которой выполняется одна или две
- небольшие операции, скажем, 1-7 строк.
-* Средняя область видимости — это несколько небольших или одна большая
- операция, скажем, 8-15 строк.
-* Большая область видимости — это одна или несколько больших операций, скажем,
- 15-25 строк.
-* Очень большая область видимости — это все, что занимает больше страницы
- (скажем, более 25 строк).
+- Малая область видимости — это область, в которой выполняется одна или две
+ небольшие операции, скажем, 1-7 строк.
+- Средняя область видимости — это несколько небольших или одна большая
+ операция, скажем, 8-15 строк.
+- Большая область видимости — это одна или несколько больших операций, скажем,
+ 15-25 строк.
+- Очень большая область видимости — это все, что занимает больше страницы
+ (скажем, более 25 строк).
[ясности]: guide#clarity
[лаконичности]: guide#concision
@@ -323,21 +318,21 @@ Txn | Экспортировано | `Txn` | `TXN`
В общем:
-* Однобуквенные имена, такие как `count` или `options`, — хорошая отправная
- точка.
-* Дополнительные слова могут быть добавлены для различения похожих имен,
- например `userCount` и `projectCount`.
-* Не просто выбрасывайте буквы, чтобы сэкономить на печати. Например,
- `Sandbox` предпочтительнее, чем `Sbx`, особенно для экспортируемых имен.
-* Опускайте [типы и слова, похожие на типы] из большинства имен переменных.
- * Для числа `userCount` — лучшее имя, чем `numUsers` или `usersInt`.
- * Для среза `users` — лучшее имя, чем `userSlice`.
- * Допустимо включать квалификатор, похожий на тип, если в области
- видимости есть две версии значения, например, у вас может быть ввод,
- сохраненный в `ageString`, и `age` для распарсенного значения.
-* Опускайте слова, которые ясны из [окружающего контекста]. Например, в
- реализации метода `UserCount` локальная переменная с именем `userCount`,
- вероятно, избыточна; `count`, `users` или даже `c` так же читаемы.
+- Однобуквенные имена, такие как `count` или `options`, — хорошая отправная
+ точка.
+- Дополнительные слова могут быть добавлены для различения похожих имен,
+ например `userCount` и `projectCount`.
+- Не просто выбрасывайте буквы, чтобы сэкономить на печати. Например,
+ `Sandbox` предпочтительнее, чем `Sbx`, особенно для экспортируемых имен.
+- Опускайте [типы и слова, похожие на типы] из большинства имен переменных.
+ - Для числа `userCount` — лучшее имя, чем `numUsers` или `usersInt`.
+ - Для среза `users` — лучшее имя, чем `userSlice`.
+ - Допустимо включать квалификатор, похожий на тип, если в области
+ видимости есть две версии значения, например, у вас может быть ввод,
+ сохраненный в `ageString`, и `age` для распарсенного значения.
+- Опускайте слова, которые ясны из [окружающего контекста]. Например, в
+ реализации метода `UserCount` локальная переменная с именем `userCount`,
+ вероятно, избыточна; `count`, `users` или даже `c` так же читаемы.
[типы и слова, похожие на типы]: #repetitive-with-type
[окружающего контекста]: #repetitive-in-context
@@ -353,17 +348,17 @@ Txn | Экспортировано | `Txn` | `TXN`
В общем:
-* Для [переменной-получателя метода] предпочтительно одно- или двухбуквенное
- имя.
-* Использование знакомых имен переменных для распространенных типов часто
- полезно:
- * `r` для `io.Reader` или `*http.Request`
- * `w` для `io.Writer` или `http.ResponseWriter`
-* Однобуквенные идентификаторы допустимы в качестве целочисленных переменных
- цикла, особенно для индексов (например, `i`) и координат (например, `x` и
- `y`).
-* Сокращения могут быть допустимыми идентификаторами цикла, если область
- видимости короткая, например `for _, n := range nodes { ... }`.
+- Для [переменной-получателя метода] предпочтительно одно- или двухбуквенное
+ имя.
+- Использование знакомых имен переменных для распространенных типов часто
+ полезно:
+ - `r` для `io.Reader` или `*http.Request`
+ - `w` для `io.Writer` или `http.ResponseWriter`
+- Однобуквенные идентификаторы допустимы в качестве целочисленных переменных
+ цикла, особенно для индексов (например, `i`) и координат (например, `x` и
+ `y`).
+- Сокращения могут быть допустимыми идентификаторами цикла, если область
+ видимости короткая, например `for _, n := range nodes { ... }`.
[переменной-получателя метода]: #receiver-names
@@ -396,28 +391,28 @@ Txn | Экспортировано | `Txn` | `TXN`
> **Примеры:** Повторяющееся имя -> Лучшее имя
>
-> * `widget.NewWidget` -> `widget.New`
-> * `widget.NewWidgetWithName` -> `widget.NewWithName`
-> * `db.LoadFromDatabase` -> `db.Load`
-> * `goatteleportutil.CountGoatsTeleported` -> `gtutil.CountGoatsTeleported`
-> или `goatteleport.Count`
-> * `myteampb.MyTeamMethodRequest` -> `mtpb.MyTeamMethodRequest` или
-> `myteampb.MethodRequest`
+> - `widget.NewWidget` -> `widget.New`
+> - `widget.NewWidgetWithName` -> `widget.NewWithName`
+> - `db.LoadFromDatabase` -> `db.Load`
+> - `goatteleportutil.CountGoatsTeleported` -> `gtutil.CountGoatsTeleported`
+> или `goatteleport.Count`
+> - `myteampb.MyTeamMethodRequest` -> `mtpb.MyTeamMethodRequest` или
+> `myteampb.MethodRequest`
<a id="repetitive-with-type"></a>
#### Имя переменной vs. тип
Компилятор всегда знает тип переменной, и в большинстве случаев читателю также
-понятен тип переменной по тому, как она используется. Уточнять тип переменной
+понятен тип переменной по тому, как она используется. Уточнять тип переменной
необходимо только если ее значение появляется дважды в одной и той же области
видимости.
-Повторяющееся имя | Лучшее имя
-------------------------------- | ----------------------
-`var numUsers int` | `var users int`
-`var nameString string` | `var name string`
-`var primaryProject *Project` | `var primary *Project`
+| Повторяющееся имя | Лучшее имя |
+| ----------------------------- | ---------------------- |
+| `var numUsers int` | `var users int` |
+| `var nameString string` | `var name string` |
+| `var primaryProject *Project` | `var primary *Project` |
Если значение появляется в нескольких формах, это можно уточнить либо с помощью
дополнительного слова, например `raw` и `parsed`, либо с помощью базового
@@ -524,7 +519,7 @@ func (db *DB) UserCount() (int, error) {
Соглашения, касающиеся комментариев (что комментировать, какой стиль
использовать, как предоставлять исполняемые примеры и т.д.), предназначены для
-поддержки удобства чтения документации публичного API. Подробнее см. [Effective
+поддержки удобства чтения документации публичного API. Подробнее см. [Effective
Go](http://golang.org/doc/effective_go.html#commentary).
Раздел о [соглашениях по документации] в документе о лучших практиках
@@ -539,7 +534,7 @@ Go](http://golang.org/doc/effective_go.html#commentary).
отступа, декорации, как правило, следует избегать.
[предпросмотр документации (doc preview)]: best-practices#documentation-preview
-[соглашениям по документации]: best-practices#documentation-conventions
+[соглашениям по документации]: best-practices#documentation-conventions
<a id="comment-line-length"></a>
@@ -551,12 +546,12 @@ Go](http://golang.org/doc/effective_go.html#commentary).
несколько однострочных комментариев. По возможности стремитесь к комментариям,
которые будут хорошо читаться на терминале шириной 80 колонок, однако это не
жесткий предел; в Go нет фиксированного ограничения длины строки для
-комментариев. Стандартная библиотека, например, часто предпочитает разрывать
+комментариев. Стандартная библиотека, например, часто предпочитает разрывать
комментарий по пунктуации, что иногда оставляет отдельные строки ближе к отметке
60-70 символов.
Существует множество существующего кода, в котором комментарии превышают 80
-символов в длину. Эти рекомендации не следует использовать как оправдание для
+символов в длину. Эти рекомендации не следует использовать как оправдание для
изменения такого кода в ходе проверки на читаемость (см.
[согласованность](https://neonxp.ru/pages/gostyleguide/google/guide/#consistency)), хотя командам рекомендуется использовать
возможность обновлять комментарии в соответствии с этим руководством в рамках
@@ -566,8 +561,7 @@ Go](http://golang.org/doc/effective_go.html#commentary).
Подробнее о комментариях см. в [этом посте из блога Go о документации].
-[этом посте из блога Go о документации]:
- https://blog.golang.org/godoc-documenting-go-code
+[этом посте из блога Go о документации]: https://blog.golang.org/godoc-documenting-go-code
```text
# Хорошо:
@@ -606,7 +600,7 @@ Go](http://golang.org/doc/effective_go.html#commentary).
Все экспортируемые имена верхнего уровня должны иметь документирующие
комментарии, как и неэкспортируемые объявления типов или функций с неочевидным
поведением или смыслом. Эти комментарии должны быть [полными предложениями],
-которые начинаются с имени описываемого объекта. Артикль ("a", "an", "the")
+которые начинаются с имени описываемого объекта. Артикль ("a", "an", "the")
может предшествовать имени, чтобы оно читалось более естественно.
```go
@@ -645,7 +639,7 @@ type Options struct {
**Лучшая практика:** Если у вас есть документирующие комментарии для
неэкспортируемого кода, следуйте тому же обычаю, как если бы он был
-экспортируемым (а именно, начиная комментарий с неэкспортируемого имени). Это
+экспортируемым (а именно, начиная комментарий с неэкспортируемого имени). Это
упрощает его экспорт позже простой заменой неэкспортируемого имени на новое
экспортируемое в комментариях и коде.
@@ -701,8 +695,7 @@ type Server struct {
[исполняемый пример]: http://blog.golang.org/examples
[Godoc]: https://pkg.go.dev/time#example-Duration
-[исходный код]:
- https://cs.opensource.google/go/go/+/HEAD:src/time/example_test.go
+[исходный код]: https://cs.opensource.google/go/go/+/HEAD:src/time/example_test.go
Если предоставить исполняемый пример нецелесообразно, пример кода может быть
предоставлен внутри комментариев к коду. Как и другие фрагменты кода и командной
@@ -716,7 +709,7 @@ type Server struct {
<a id="TOC-NamedResultParameters"></a>
При именовании параметров учитывайте, как сигнатуры функций отображаются в
-Godoc. Имя самой функции и тип возвращаемых параметров часто достаточно ясны.
+Godoc. Имя самой функции и тип возвращаемых параметров часто достаточно ясны.
```go
// Хорошо:
@@ -747,7 +740,7 @@ func WithTimeout(parent Context, d time.Duration) (ctx Context, cancel func())
```
В приведенном выше коде отмена — это конкретное действие, которое должна
-выполнить вызывающая сторона. Однако, если бы возвращаемые параметры были
+выполнить вызывающая сторона. Однако, если бы возвращаемые параметры были
записаны просто как `(Context, func())`, было бы неясно, что подразумевается под
"функцией отмены".
@@ -761,13 +754,13 @@ func (n *Node) Parent2() (node *Node, err error)
```
Не называйте возвращаемые параметры, чтобы избежать объявления переменной внутри
-функции. Эта практика приводит к излишней многословности API в обмен на
+функции. Эта практика приводит к излишней многословности API в обмен на
незначительную краткость реализации.
[Голые возвраты (Naked returns)] допустимы только в маленькой функции. Как
только это функция среднего размера, будьте явны со своими возвращаемыми
значениями. Аналогично, не называйте возвращаемые параметры только потому, что
-это позволяет вам использовать голые возвраты. [Ясность](https://neonxp.ru/pages/gostyleguide/google/guide/#clarity) всегда
+это позволяет вам использовать голые возвраты. [Ясность](https://neonxp.ru/pages/gostyleguide/google/guide/#clarity) всегда
важнее, чем сэкономить несколько строк в вашей функции.
Всегда приемлемо назвать возвращаемый параметр, если его значение должно быть
@@ -781,8 +774,7 @@ func (n *Node) Parent2() (node *Node, err error)
> документирования.
[Голые возвраты (Naked returns)]: https://tour.golang.org/basics/7
-[GoTip #38: Функции как именованные типы]:
- https://google.github.io/styleguide/go/index.html#gotip
+[GoTip #38: Функции как именованные типы]: /pages/gostyleguide/google/index.html#gotip
[`WithTimeout`]: https://pkg.go.dev/context#WithTimeout
[`CancelFunc`]: https://pkg.go.dev/context#CancelFunc
@@ -832,19 +824,19 @@ package main
Советы:
-* Примеры вызовов командной строки и использования API могут быть полезной
- документацией. Для форматирования Godoc сделайте отступ для строк
- комментария, содержащих код.
+- Примеры вызовов командной строки и использования API могут быть полезной
+ документацией. Для форматирования Godoc сделайте отступ для строк
+ комментария, содержащих код.
-* Если нет очевидного основного файла или если комментарий к пакету необычайно
- длинный, допустимо поместить документирующий комментарий в файл с именем
- `doc.go`, содержащий только комментарий и объявление пакета.
+- Если нет очевидного основного файла или если комментарий к пакету необычайно
+ длинный, допустимо поместить документирующий комментарий в файл с именем
+ `doc.go`, содержащий только комментарий и объявление пакета.
-* Многострочные комментарии могут использоваться вместо нескольких
- однострочных. Это в первую очередь полезно, если документация содержит
- разделы, которые могут быть полезны для копирования и вставки из исходного
- файла, как, например, примеры командной строки (для бинарников) и примеры
- шаблонов.
+- Многострочные комментарии могут использоваться вместо нескольких
+ однострочных. Это в первую очередь полезно, если документация содержит
+ разделы, которые могут быть полезны для копирования и вставки из исходного
+ файла, как, например, примеры командной строки (для бинарников) и примеры
+ шаблонов.
```go
// Хорошо:
@@ -857,9 +849,9 @@ package main
package template
```
-* Комментарии, предназначенные для сопровождающих и относящиеся ко всему
- файлу, обычно размещаются после объявлений импорта. Они не отображаются в
- Godoc и не подчиняются приведенным выше правилам для комментариев к пакетам.
+- Комментарии, предназначенные для сопровождающих и относящиеся ко всему
+ файлу, обычно размещаются после объявлений импорта. Они не отображаются в
+ Godoc и не подчиняются приведенным выше правилам для комментариев к пакетам.
<a id="imports"></a>
@@ -880,15 +872,15 @@ package main
[последовательными](https://neonxp.ru/pages/gostyleguide/google/guide/#consistency), всегда используя одно и то же локальное
имя для одного и того же импортированного пакета.
-Импортированный пакет *должен* быть переименован, чтобы избежать конфликта имен
+Импортированный пакет _должен_ быть переименован, чтобы избежать конфликта имен
с другими импортами. (Следствие из этого: [хорошие имена
пакетов](#package-names) не должны требовать переименования.) В случае конфликта
имен предпочтительнее переименовать наиболее локальный или специфичный для
проекта импорт.
-Сгенерированные пакеты протоколов буфера *должны* быть переименованы, чтобы
+Сгенерированные пакеты протоколов буфера _должны_ быть переименованы, чтобы
удалить подчеркивания из их имен, и их локальные имена должны иметь суффикс
-`pb`. Подробнее см. [лучшие практики для proto и заглушек
+`pb`. Подробнее см. [лучшие практики для proto и заглушек
(stubs)](https://neonxp.ru/pages/gostyleguide/google/best-practices/#import-protos).
```go
@@ -898,10 +890,10 @@ import (
)
```
-Наконец, импортированный, несгенерированный пакет *может* быть переименован,
+Наконец, импортированный, несгенерированный пакет _может_ быть переименован,
если он имеет неинформативное имя (например, `util` или `v1`) Делайте это
экономно: не переименовывайте пакет, если код, окружающий использование пакета,
-передает достаточно контекста. По возможности предпочитайте рефакторинг самого
+передает достаточно контекста. По возможности предпочитайте рефакторинг самого
пакета с более подходящим именем.
```go
@@ -915,7 +907,7 @@ import (
Если вам нужно импортировать пакет, имя которого конфликтует с распространенным
локальным именем переменной, которое вы хотите использовать (например, `url`,
`ssh`), и вы хотите переименовать пакет, предпочтительный способ сделать это —
-использовать суффикс `pkg` (например, `urlpkg`). Обратите внимание, что
+использовать суффикс `pkg` (например, `urlpkg`). Обратите внимание, что
возможно затенение пакета локальной переменной; это переименование необходимо
только если пакет все еще нужно использовать, когда такая переменная находится в
области видимости.
@@ -934,7 +926,7 @@ import (
1. Импорт для [побочных эффектов (side
effects)](https://go.dev/doc/effective_go#blank_import) (например, `_
- "path/to/package"`)
+"path/to/package"`)
```go
// Хорошо:
@@ -968,9 +960,9 @@ import (
Некоторые примеры таких пакетов:
-* [time/tzdata](https://pkg.go.dev/time/tzdata)
+- [time/tzdata](https://pkg.go.dev/time/tzdata)
-* [image/jpeg](https://pkg.go.dev/image/jpeg) в коде обработки изображений
+- [image/jpeg](https://pkg.go.dev/image/jpeg) в коде обработки изображений
Избегайте пустых импортов в библиотечных пакетах, даже если библиотека косвенно
зависит от них. Ограничение импортов с побочными эффектами главным пакетом
@@ -979,19 +971,18 @@ import (
Следующие исключения являются единственными для этого правила:
-* Вы можете использовать пустой импорт, чтобы обойти проверку на запрещенные
- импорты в [статическом анализаторе nogo].
+- Вы можете использовать пустой импорт, чтобы обойти проверку на запрещенные
+ импорты в [статическом анализаторе nogo].
-* Вы можете использовать пустой импорт пакета
- [embed](https://pkg.go.dev/embed) в исходном файле, который использует
- директиву компилятора `//go:embed`.
+- Вы можете использовать пустой импорт пакета
+ [embed](https://pkg.go.dev/embed) в исходном файле, который использует
+ директиву компилятора `//go:embed`.
**Совет:** Если вы создаете библиотечный пакет, который косвенно зависит от
импорта с побочным эффектом в продакшене, задокументируйте предполагаемое
использование.
-[статическом анализаторе nogo]:
- https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst
+[статическом анализаторе nogo]: https://github.com/bazelbuild/rules_go/blob/master/go/nogo.rst
<a id="import-dot"></a>
@@ -1001,7 +992,7 @@ import (
Форма `import .` — это языковая возможность, позволяющая переносить
идентификаторы, экспортированные из другого пакета, в текущий пакет без
-квалификации. Подробнее см. [спецификацию
+квалификации. Подробнее см. [спецификацию
языка](https://go.dev/ref/spec#Import_declarations).
Не **используйте** эту возможность в кодовой базе Google; это затрудняет
@@ -1068,9 +1059,9 @@ func GoodLookup() (*Result, error) {
```
Экспортируемые функции, возвращающие ошибки, должны возвращать их, используя тип
-`error`. Конкретные типы ошибок подвержены тонким ошибкам: конкретный `nil`
+`error`. Конкретные типы ошибок подвержены тонким ошибкам: конкретный `nil`
указатель может быть завернут в интерфейс и таким образом стать ненулевым
-значением (см. [FAQ по Go на эту тему][nil error]).
+значением (см. [FAQ по Go на эту тему][nil error]).
```go
// Плохо:
@@ -1123,13 +1114,13 @@ t.Errorf("Op(%q) failed unexpectedly; err=%v", args, err)
Код, который сталкивается с ошибкой, должен принять осознанное решение о том,
как ее обработать. Обычно нецелесообразно отбрасывать ошибки, используя
-переменные `_`. Если функция возвращает ошибку, сделайте одно из следующих
+переменные `_`. Если функция возвращает ошибку, сделайте одно из следующих
действий:
-* Обработайте и исправьте ошибку немедленно.
-* Верните ошибку вызывающей стороне.
-* В исключительных ситуациях вызовите [`log.Fatal`] или (если абсолютно
- необходимо) `panic`.
+- Обработайте и исправьте ошибку немедленно.
+- Верните ошибку вызывающей стороне.
+- В исключительных ситуациях вызовите [`log.Fatal`] или (если абсолютно
+ необходимо) `panic`.
**Примечание:** `log.Fatalf` здесь не из стандартной библиотеки log. См.
[#logging].
@@ -1146,7 +1137,7 @@ var b *bytes.Buffer
n, _ := b.Write(p) // никогда не возвращает ненулевую ошибку
```
-Для дальнейшего обсуждения и примеров обработки ошибок см. [Effective
+Для дальнейшего обсуждения и примеров обработки ошибок см. [Effective
Go](http://golang.org/doc/effective_go.html#errors) и [лучшие
практики](https://neonxp.ru/pages/gostyleguide/google/best-practices/.md#error-handling).
@@ -1179,7 +1170,7 @@ return Parse(Lookup(missingKey))
```
Поддержка Go нескольких возвращаемых значений предоставляет лучшее решение (см.
-[раздел Effective Go о множественных возвращаемых значениях]). Вместо того
+[раздел Effective Go о множественных возвращаемых значениях]). Вместо того
чтобы требовать от клиентов проверять значение ошибки "в потоке", функция должна
возвращать дополнительное значение, чтобы указать, являются ли ее другие
возвращаемые значения валидными. Это возвращаемое значение может быть ошибкой
@@ -1209,13 +1200,12 @@ return Parse(value)
```
Некоторые функции стандартной библиотеки, например в пакете `strings`,
-возвращают значения ошибок "в потоке". Это значительно упрощает код для
+возвращают значения ошибок "в потоке". Это значительно упрощает код для
манипуляций со строками за счет необходимости большей внимательности от
программиста. В целом, код Go в кодовой базе Google должен возвращать
дополнительные значения для ошибок.
-[раздел Effective Go о множественных возвращаемых значениях]:
- http://golang.org/doc/effective_go.html#multiple-returns
+[раздел Effective Go о множественных возвращаемых значениях]: http://golang.org/doc/effective_go.html#multiple-returns
<a id="indent-error-flow"></a>
@@ -1280,8 +1270,7 @@ if err != nil {
Complexity by Reducing
Nesting](https://testing.googleblog.com/2017/06/code-health-reduce-nesting-reduce.html).
-[Go Tip #1: Линия видимости (Line of Sight)]:
- https://google.github.io/styleguide/go/index.html#gotip
+[Go Tip #1: Линия видимости (Line of Sight)]: /pages/gostyleguide/google/index.html#gotip
<a id="language"></a>
@@ -1298,8 +1287,7 @@ Go обладает исключительно мощным [синтаксис
довольно хорошее, но существуют некоторые дополнительные правила для сохранения
читаемости и поддерживаемости этих литералов.
-[синтаксисом составных литералов]:
- https://golang.org/ref/spec#Composite_literals
+[синтаксисом составных литералов]: https://golang.org/ref/spec#Composite_literals
<a id="literal-field-names"></a>
@@ -1308,7 +1296,7 @@ Go обладает исключительно мощным [синтаксис
Литералы структур должны указывать **имена полей** для типов, определенных вне
текущего пакета.
-* Включайте имена полей для типов из других пакетов.
+- Включайте имена полей для типов из других пакетов.
```go
// Хорошо:
@@ -1330,7 +1318,7 @@ Go обладает исключительно мощным [синтаксис
r := csv.Reader{',', '#', 4, false, false, false, false}
```
-* Для локальных типов пакета имена полей не обязательны.
+- Для локальных типов пакета имена полей не обязательны.
```go
// Хорошо:
@@ -1342,7 +1330,7 @@ Go обладает исключительно мощным [синтаксис
очень распространено. Например, структуру с большим количеством полей почти
всегда следует инициализировать с указанием имен полей.
- <!-- TODO: Maybe a better example here that doesn't have many fields. -->
+ <!-- TODO: Maybe a better example here that doesn't have many fields. -->
```go
// Хорошо:
@@ -1406,9 +1394,9 @@ bad := []*Type{
литералов срезов и массивов допустимо только когда оба следующих условия
истинны.
-* [Отступы совпадают](#literal-matching-braces)
-* Внутренние значения также являются литералами или сборщиками protobuf (то
- есть не переменной или другим выражением)
+- [Отступы совпадают](#literal-matching-braces)
+- Внутренние значения также являются литералами или сборщиками protobuf (то
+ есть не переменной или другим выражением)
```go
// Хорошо:
@@ -1557,7 +1545,7 @@ ldb := leveldb.Open("/my/table", &db.Options{
когда тестовая структура нетривиальна. Это позволяет автору опускать поля с
нулевыми значениями полностью, когда рассматриваемые поля не относятся к
тестовому случаю. Например, успешные тестовые случаи должны опускать любые поля,
-связанные с ошибками или неудачами. В случаях, когда нулевое значение
+связанные с ошибками или неудачами. В случаях, когда нулевое значение
необходимо для понимания тестового случая, таких как тестирование нулевых или
`nil` входных данных, имена полей должны быть указаны.
@@ -1724,9 +1712,9 @@ if longCondition1 && longCondition2 &&
См. следующие разделы для конкретных рекомендаций и примеров:
-* [Форматирование функций](#func-formatting)
-* [Условные операторы и циклы](#conditional-formatting)
-* [Форматирование литералов](#literal-formatting)
+- [Форматирование функций](#func-formatting)
+- [Условные операторы и циклы](#conditional-formatting)
+- [Форматирование литералов](#literal-formatting)
<a id="func-formatting"></a>
@@ -1776,7 +1764,7 @@ bad := foo.Call(long, list, of, parameters,
```
По возможности избегайте добавления встроенных комментариев к конкретным
-аргументам функций. Вместо этого используйте [структуру опций (option
+аргументам функций. Вместо этого используйте [структуру опций (option
struct)](https://neonxp.ru/pages/gostyleguide/google/best-practices/#option-structure) или добавьте больше деталей в
документацию функции.
@@ -1814,9 +1802,9 @@ canvas.RenderHeptagon(fillColor,
определенную границу столбца, а группируются на основе координат вершин и цвета.
Длинные строковые литералы внутри функций не должны разбиваться ради длины
-строки. Для функций, включающих такие строки, разрыв строки можно добавить
+строки. Для функций, включающих такие строки, разрыв строки можно добавить
после формата строки, а аргументы могут быть предоставлены на следующей или
-последующих строках. Решение о том, где должны быть разрывы строк, лучше всего
+последующих строках. Решение о том, где должны быть разрывы строк, лучше всего
принимать на основе семантических групп входных данных, а не исключительно на
основе длины строки.
@@ -2206,13 +2194,13 @@ ch <- 13 // panic
произвольное время может привести к непредсказуемому использованию памяти.
Параллельный код должен быть написан так, чтобы время жизни горутин было
-очевидным. Обычно это означает сохранение кода, связанного с синхронизацией, в
+очевидным. Обычно это означает сохранение кода, связанного с синхронизацией, в
пределах области видимости функции и вынесение логики в [синхронные функции].
Если параллелизм все еще не очевиден, важно задокументировать, когда и почему
горутины завершаются.
Код, следующий лучшим практикам использования контекста, часто помогает
-прояснить это. Обычно это управляется с помощью [`context.Context`]:
+прояснить это. Обычно это управляется с помощью [`context.Context`]:
```go
// Хорошо:
@@ -2255,31 +2243,28 @@ func (w *Worker) Run() {
Этот код может выглядеть нормально, но у него есть несколько скрытых проблем:
-* Код, вероятно, имеет неопределенное поведение в продакшене, и программа
- может не завершиться чисто, даже если операционная система освободит
- ресурсы.
+- Код, вероятно, имеет неопределенное поведение в продакшене, и программа
+ может не завершиться чисто, даже если операционная система освободит
+ ресурсы.
-* Код трудно осмысленно протестировать из-за неопределенного жизненного цикла.
+- Код трудно осмысленно протестировать из-за неопределенного жизненного цикла.
-* Код может подтекать ресурсами, как описано выше.
+- Код может подтекать ресурсами, как описано выше.
См. также:
-* [Никогда не запускайте горутину, не зная, как она остановится][cheney-stop]
-* Переосмысление классических паттернов параллелизма:
- [слайды][rethinking-slides], [видео][rethinking-video]
-* [Когда программы на Go завершаются]
-* [Соглашения по документации: Контексты]
+- [Никогда не запускайте горутину, не зная, как она остановится][cheney-stop]
+- Переосмысление классических паттернов параллелизма:
+ [слайды][rethinking-slides], [видео][rethinking-video]
+- [Когда программы на Go завершаются]
+- [Соглашения по документации: Контексты]
[синхронные функции]: #synchronous-functions
-[cheney-stop]:
- https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop
-[rethinking-slides]:
- https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view
+[cheney-stop]: https://dave.cheney.net/2016/12/22/never-start-a-goroutine-without-knowing-how-it-will-stop
+[rethinking-slides]: https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view
[rethinking-video]: https://www.youtube.com/watch?v=5zXAHh5tJqQ
[Когда программы на Go завершаются]: https://changelog.com/gotime/165
-[Соглашения по документации: Контексты]:
- best-practices.md#documentation-conventions-contexts
+[Соглашения по документации: Контексты]: best-practices.md#documentation-conventions-contexts
<a id="interfaces"></a>
@@ -2287,9 +2272,9 @@ func (w *Worker) Run() {
<a id="TOC-Interfaces"></a>
-Интерфейсы Go обычно принадлежат пакету, который *потребляет* значения типа
-интерфейса, а не пакету, который *реализует* тип интерфейса. Реализующий пакет
-должен возвращать конкретные (обычно указатель или структура) типы. Таким
+Интерфейсы Go обычно принадлежат пакету, который _потребляет_ значения типа
+интерфейса, а не пакету, который _реализует_ тип интерфейса. Реализующий пакет
+должен возвращать конкретные (обычно указатель или структура) типы. Таким
образом, новые методы могут быть добавлены к реализациям без необходимости
обширного рефакторинга. Подробнее см. [GoTip #49: Принимайте интерфейсы,
возвращайте конкретные типы].
@@ -2297,7 +2282,7 @@ func (w *Worker) Run() {
Не экспортируйте [тестовый дубль (test double)][double types] реализации
интерфейса из API, который его потребляет. Вместо этого спроектируйте API так,
чтобы его можно было тестировать с помощью [публичного API] [реальной
-реализации]. См. [GoTip #42: Создание заглушки для тестирования] для
+реализации]. См. [GoTip #42: Создание заглушки для тестирования] для
подробностей. Даже когда нецелесообразно использовать реальную реализацию, может
не потребоваться вводить интерфейс, полностью покрывающий все методы в реальном
типе; потребитель может создать интерфейс, содержащий только нужные ему методы,
@@ -2308,7 +2293,7 @@ func (w *Worker) Run() {
внутренняя практика Google — получить реальное клиентское соединение с локальным
[тестовым дублем] с использованием внутреннего пакета rpctest (скоро будет!).
-Не определяйте интерфейсы до того, как они используются (см. [TotT: Code
+Не определяйте интерфейсы до того, как они используются (см. [TotT: Code
Health: Eliminate YAGNI Smells][tott-438] ). Без реалистичного примера
использования слишком сложно увидеть, нужен ли интерфейс вообще, не говоря уже о
том, какие методы он должен содержать.
@@ -2321,21 +2306,14 @@ Health: Eliminate YAGNI Smells][tott-438] ). Без реалистичного
**TODO:** Написать более подробный документ об интерфейсах и дать на него ссылку
здесь.
-[GoTip #42: Создание заглушки для тестирования]:
- https://google.github.io/styleguide/go/index.html#gotip
-[GoTip #49: Принимайте интерфейсы, возвращайте конкретные типы]:
- https://google.github.io/styleguide/go/index.html#gotip
-[GoTip #78: Минимально жизнеспособные интерфейсы]:
- https://google.github.io/styleguide/go/index.html#gotip
+[GoTip #42: Создание заглушки для тестирования]: /pages/gostyleguide/google/index.html#gotip
+[GoTip #49: Принимайте интерфейсы, возвращайте конкретные типы]: /pages/gostyleguide/google/index.html#gotip
+[GoTip #78: Минимально жизнеспособные интерфейсы]: /pages/gostyleguide/google/index.html#gotip
[реальной реализации]: best-practices#use-real-transports
-[публичному API]:
- https://abseil.io/resources/swe-book/html/ch12.html#test_via_public_apis
-[double types]:
- https://abseil.io/resources/swe-book/html/ch13.html#techniques_for_using_test_doubles
-[тестовым дублем]:
- https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts
-[tott-438]:
- https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html
+[публичному API]: https://abseil.io/resources/swe-book/html/ch12.html#test_via_public_apis
+[double types]: https://abseil.io/resources/swe-book/html/ch13.html#techniques_for_using_test_doubles
+[тестовым дублем]: https://abseil.io/resources/swe-book/html/ch13.html#basic_concepts
+[tott-438]: https://testing.googleblog.com/2017/08/code-health-eliminate-yagni-smells.html
```go
// Хорошо:
@@ -2396,39 +2374,38 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
Не используйте дженерики только потому, что вы реализуете алгоритм или структуру
данных, которой не важен тип элементов. Если на практике инстанцируется только
один тип, начните с того, чтобы ваш код работал с этим типом без использования
-дженериков вообще. Добавить полиморфизм позже будет проще по сравнению с
+дженериков вообще. Добавить полиморфизм позже будет проще по сравнению с
удалением абстракции, которая оказывается ненужной.
Не используйте дженерики для создания предметно-ориентированных языков (DSL). В
частности, воздержитесь от введения фреймворков обработки ошибок, которые могут
значительно обременять читателей. Вместо этого предпочитайте установленные
-методы [обработки ошибок](#errors). Для тестирования особенно остерегайтесь
+методы [обработки ошибок](#errors). Для тестирования особенно остерегайтесь
введения [библиотек утверждений (assertion libraries)](#assert) или фреймворков,
которые приводят к менее полезным [сообщениям об ошибках
тестов](#useful-test-failures).
В общем:
-* [Пишите код, не проектируйте типы]. Из выступления на GopherCon от Роберта
- Грисемера и Яна Лэнса Тейлора.
-* Если у вас есть несколько типов, которые разделяют полезный объединяющий
- интерфейс, рассмотрите моделирование решения с использованием этого
- интерфейса. Дженерики могут не понадобиться.
-* В противном случае вместо того, чтобы полагаться на тип `any` и чрезмерное
- [переключение типов (type switching)](https://tour.golang.org/methods/16),
- рассмотрите дженерики.
+- [Пишите код, не проектируйте типы]. Из выступления на GopherCon от Роберта
+ Грисемера и Яна Лэнса Тейлора.
+- Если у вас есть несколько типов, которые разделяют полезный объединяющий
+ интерфейс, рассмотрите моделирование решения с использованием этого
+ интерфейса. Дженерики могут не понадобиться.
+- В противном случае вместо того, чтобы полагаться на тип `any` и чрезмерное
+ [переключение типов (type switching)](https://tour.golang.org/methods/16),
+ рассмотрите дженерики.
См. также:
-* [Использование дженериков в Go], выступление Яна Лэнса Тейлора
+- [Использование дженериков в Go], выступление Яна Лэнса Тейлора
-* [Учебник по дженерикам] на сайте Go
+- [Учебник по дженерикам] на сайте Go
[Учебник по дженерикам]: https://go.dev/doc/tutorial/generics
[Параметрами типа]: https://go.dev/design/43651-type-parameters
[Использование дженериков в Go]: https://www.youtube.com/watch?v=nr8EpUO9jhw
-[Пишите код, не проектируйте типы]:
- https://www.youtube.com/watch?v=Pa_e9EeCdy8&t=1250s
+[Пишите код, не проектируйте типы]: https://www.youtube.com/watch?v=Pa_e9EeCdy8&t=1250s
<a id="pass-values"></a>
@@ -2471,8 +2448,8 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
Список ниже подробно описывает каждый случай:
-* Если получатель является срезом и метод не переслаивает (reslice) и не
- перераспределяет (reallocate) срез, используйте значение, а не указатель.
+- Если получатель является срезом и метод не переслаивает (reslice) и не
+ перераспределяет (reallocate) срез, используйте значение, а не указатель.
```go
// Хорошо:
@@ -2481,7 +2458,7 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
func (b Buffer) Len() int { return len(b) }
```
-* Если методу нужно мутировать получателя, получатель должен быть указателем.
+- Если методу нужно мутировать получателя, получатель должен быть указателем.
```go
// Хорошо:
@@ -2495,9 +2472,9 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
func (q *Queue) Push(x Item) { *q = append([]Item{x}, *q...) }
```
-* Если получатель является структурой, содержащей поля, которые [не могут быть
- безопасно скопированы](#copying), используйте получатель-указатель.
- Распространенные примеры — [`sync.Mutex`] и другие типы синхронизации.
+- Если получатель является структурой, содержащей поля, которые [не могут быть
+ безопасно скопированы](#copying), используйте получатель-указатель.
+ Распространенные примеры — [`sync.Mutex`] и другие типы синхронизации.
```go
// Хорошо:
@@ -2516,21 +2493,21 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
**Совет:** Проверьте [Godoc] типа для информации о том, безопасно ли или
небезопасно его копировать.
-* Если получатель является "большой" структурой или массивом,
- получатель-указатель может быть более эффективным. Передача структуры
- эквивалентна передаче всех ее полей или элементов в качестве аргументов
- методу. Если это кажется слишком большим для [передачи по
- значению](#pass-values), указатель — хороший выбор.
+- Если получатель является "большой" структурой или массивом,
+ получатель-указатель может быть более эффективным. Передача структуры
+ эквивалентна передаче всех ее полей или элементов в качестве аргументов
+ методу. Если это кажется слишком большим для [передачи по
+ значению](#pass-values), указатель — хороший выбор.
-* Для методов, которые будут вызываться или выполняться параллельно с другими
- функциями, которые изменяют получателя, используйте значение, если эти
- изменения не должны быть видны вашему методу; в противном случае используйте
- указатель.
+- Для методов, которые будут вызываться или выполняться параллельно с другими
+ функциями, которые изменяют получателя, используйте значение, если эти
+ изменения не должны быть видны вашему методу; в противном случае используйте
+ указатель.
-* Если получатель является структурой или массивом, любой элемент которого
- является указателем на что-то, что может быть изменено, предпочтите
- получателя-указателя, чтобы сделать намерение изменяемости понятным для
- читателя.
+- Если получатель является структурой или массивом, любой элемент которого
+ является указателем на что-то, что может быть изменено, предпочтите
+ получателя-указателя, чтобы сделать намерение изменяемости понятным для
+ читателя.
```go
// Хорошо:
@@ -2543,8 +2520,8 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
}
```
-* Если получатель является [встроенным типом], таким как целое число или
- строка, который не нужно изменять, используйте значение.
+- Если получатель является [встроенным типом], таким как целое число или
+ строка, который не нужно изменять, используйте значение.
```go
// Хорошо:
@@ -2553,8 +2530,8 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
func (u User) String() { return string(u) }
```
-* Если получатель является картой (map), функцией или каналом, используйте
- значение, а не указатель.
+- Если получатель является картой (map), функцией или каналом, используйте
+ значение, а не указатель.
```go
// Хорошо:
@@ -2564,9 +2541,9 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
func (h Header) Add(key, value string) { /* опущено */ }
```
-* Если получатель является "маленьким" массивом или структурой, которые
- естественным образом являются типом значения без изменяемых полей и без
- указателей, получатель по значению обычно является правильным выбором.
+- Если получатель является "маленьким" массивом или структурой, которые
+ естественным образом являются типом значения без изменяемых полей и без
+ указателей, получатель по значению обычно является правильным выбором.
```go
// Хорошо:
@@ -2576,7 +2553,7 @@ mechanism)](https://neonxp.ru/pages/gostyleguide/google/guide/#least-mechanism).
func (t Time) Add(d Duration) Time { /* опущено */ }
```
-* В случае сомнений используйте получатель-указатель.
+- В случае сомнений используйте получатель-указатель.
В качестве общего руководства предпочитайте, чтобы методы для типа были либо все
указательными методами, либо всеми методами по значению.
@@ -2676,8 +2653,8 @@ default:
См. также:
-* "Переосмысление классических паттернов параллелизма", выступление Брайана
- Миллса: [слайды][rethinking-slides], [видео][rethinking-video]
+- "Переосмысление классических паттернов параллелизма", выступление Брайана
+ Миллса: [слайды][rethinking-slides], [видео][rethinking-video]
<a id="type-aliases"></a>
@@ -2685,7 +2662,7 @@ default:
<a id="TOC-TypeAliases"></a>
-Используйте *определение типа*, `type T1 T2`, чтобы определить новый тип.
+Используйте _определение типа_, `type T1 T2`, чтобы определить новый тип.
Используйте [*псевдоним типа*], `type T1 = T2`, чтобы ссылаться на существующий
тип без определения нового типа. Псевдонимы типов редки; их основное
использование — помочь в переносе пакетов в новые места исходного кода. Не
@@ -2730,8 +2707,7 @@ Go 1.18 вводит тип `any` как [псевдоним] для `interface{
легко взаимозаменяем через явное преобразование. Предпочитайте использовать
`any` в новом коде.
-[псевдоним]:
- https://go.googlesource.com/proposal/+/master/design/18130-type-alias.md
+[псевдоним]: https://go.googlesource.com/proposal/+/master/design/18130-type-alias.md
## Общие библиотеки
@@ -2782,11 +2758,11 @@ var (
См. также:
-* [Tip of the Week #45: Avoid Flags, Especially in Library Code][totw-45]
-* [Go Tip #10: Configuration Structs and
- Flags](https://google.github.io/styleguide/go/index.html#gotip)
-* [Go Tip #80: Dependency Injection
- Principles](https://google.github.io/styleguide/go/index.html#gotip)
+- [Tip of the Week #45: Avoid Flags, Especially in Library Code][totw-45]
+- [Go Tip #10: Configuration Structs and
+ Flags](/pages/gostyleguide/google/index.html#gotip)
+- [Go Tip #80: Dependency Injection
+ Principles](/pages/gostyleguide/google/index.html#gotip)
[стандартного пакета `flag`]: https://golang.org/pkg/flag/
[mixed caps]: guide#mixed-caps
@@ -2813,11 +2789,11 @@ var (
См. также:
-* Лучшие практики по [логированию ошибок](https://neonxp.ru/pages/gostyleguide/google/best-practices/#error-logging) и
- [пользовательским уровням детализации (verbosity
- levels)](https://neonxp.ru/pages/gostyleguide/google/best-practices/#vlog)
-* Когда и как использовать пакет log для [остановки
- программы](https://neonxp.ru/pages/gostyleguide/google/best-practices/#checks-and-panics)
+- Лучшие практики по [логированию ошибок](https://neonxp.ru/pages/gostyleguide/google/best-practices/#error-logging) и
+ [пользовательским уровням детализации (verbosity
+ levels)](https://neonxp.ru/pages/gostyleguide/google/best-practices/#vlog)
+- Когда и как использовать пакет log для [остановки
+ программы](https://neonxp.ru/pages/gostyleguide/google/best-practices/#checks-and-panics)
[`log`]: https://pkg.go.dev/log
[`log/slog`]: https://pkg.go.dev/log/slog
@@ -2832,7 +2808,7 @@ var (
<a id="TOC-Contexts"></a>
Значения типа [`context.Context`] несут учетные данные безопасности, информацию
-трассировки, сроки и сигналы отмены через границы API и процессов. В отличие от
+трассировки, сроки и сигналы отмены через границы API и процессов. В отличие от
C++ и Java, которые в кодовой базе Google используют локальное хранилище потоков
(thread-local storage), программы Go передают контексты явно вдоль всей цепочки
вызовов функций от входящих RPC и HTTP запросов к исходящим запросам.
@@ -2848,25 +2824,24 @@ func F(ctx context.Context /* другие аргументы */) {}
Исключения:
-* В HTTP обработчике, где контекст берется из
- [`req.Context()`](https://pkg.go.dev/net/http#Request.Context).
-* В потоковых RPC методах, где контекст берется из потока.
+- В HTTP обработчике, где контекст берется из
+ [`req.Context()`](https://pkg.go.dev/net/http#Request.Context).
+- В потоковых RPC методах, где контекст берется из потока.
Код, использующий потоковый gRPC, получает контекст из метода `Context()` в
сгенерированном типе сервера, который реализует `grpc.ServerStream`. См.
[документацию по сгенерированному коду
gRPC](https://grpc.io/docs/languages/go/generated-code/).
-* В точках входа (entrypoint functions) (см. ниже примеры таких функций)
- используйте [`context.Background()`] или, для тестов,
- [`tb.Context()`](https://pkg.go.dev/testing#TB.Context).
-
- * В бинарных целях: `main`
- * В общем коде и библиотеках: `init`
- * В тестах: `TestXXX`, `BenchmarkXXX`, `FuzzXXX`
+- В точках входа (entrypoint functions) (см. ниже примеры таких функций)
+ используйте [`context.Background()`] или, для тестов,
+ [`tb.Context()`](https://pkg.go.dev/testing#TB.Context).
+ - В бинарных целях: `main`
+ - В общем коде и библиотеках: `init`
+ - В тестах: `TestXXX`, `BenchmarkXXX`, `FuzzXXX`
> **Примечание**: Очень редко код в середине цепочки вызовов требует создания
-> базового контекста самостоятельно с помощью [`context.Background()`]. Всегда
+> базового контекста самостоятельно с помощью [`context.Background()`]. Всегда
> предпочитайте брать контекст у вашего вызывающего, если это не неправильный
> контекст.
>
@@ -2881,7 +2856,7 @@ func F(ctx context.Context /* другие аргументы */) {}
> Если вы не реализуете серверный фреймворк, вы не должны создавать контексты с
> помощью [`context.Background()`] в библиотечном коде. Вместо этого
> предпочитайте использование отсоединения контекста (context detachment),
-> которое упоминается ниже, если доступен существующий контекст. Если вы
+> которое упоминается ниже, если доступен существующий контекст. Если вы
> думаете, что вам действительно нужно [`context.Background()`] вне функций
> точек входа, обсудите это со списком рассылки Google Go style, прежде чем
> приступать к реализации.
@@ -2922,7 +2897,7 @@ context в каждый метод типа, которому нужно пер
См. также:
-* [Контексты и структуры]
+- [Контексты и структуры]
[`context.Background()`]: https://pkg.go.dev/context/#Background
[Контексты и структуры]: https://go.dev/blog/context-and-structs
@@ -2943,7 +2918,7 @@ context в каждый метод типа, которому нужно пер
Если у вас есть данные приложения для передачи, поместите их в параметр, в
получателе, в глобальных переменных или в значении `Context`, если они
-действительно принадлежат там. Создание вашего собственного типа контекста
+действительно принадлежат там. Создание вашего собственного типа контекста
неприемлемо, поскольку оно подрывает способность команды Go заставить программы
Go правильно работать в продакшене.
@@ -2991,13 +2966,13 @@ func Key() string {
<a id="TOC-UsefulTestFailures"></a>
Должна быть возможность диагностировать неудачу теста без чтения исходного кода
-теста. Тесты должны завершаться неудачей с полезными сообщениями,
+теста. Тесты должны завершаться неудачей с полезными сообщениями,
детализирующими:
-* Что вызвало неудачу
-* Какие входные данные привели к ошибке
-* Фактический результат
-* Что ожидалось
+- Что вызвало неудачу
+- Какие входные данные привели к ошибке
+- Фактический результат
+- Что ожидалось
Конкретные соглашения для достижения этой цели изложены ниже.
@@ -3052,7 +3027,7 @@ func StringEq(t *testing.T, name, got, want string) {
библиотеку утверждений использовать, какой стиль формата вывода она должна
выдавать и т.д.? Фрагментация создает ненужную путаницу, особенно для
сопровождающих библиотек и авторов крупномасштабных изменений, которые отвечают
-за исправление потенциальных поломок вниз по течению. Вместо создания
+за исправление потенциальных поломок вниз по течению. Вместо создания
предметно-ориентированного языка для тестирования используйте сам Go.
Библиотеки утверждений часто выносят сравнения и проверки равенства.
@@ -3095,11 +3070,11 @@ func TestBlogPost_VeritableRant(t *testing.T) {
См. также:
-* [Сравнение равенства и разницы (diffs)](#types-of-equality)
-* [Печать разниц (diffs)](#print-diffs)
-* Подробнее о различии между тестовыми помощниками и помощниками утверждений
- см. [лучшие практики](https://neonxp.ru/pages/gostyleguide/google/best-practices/#test-functions)
-* Раздел [Go FAQ] о [фреймворках тестирования] и их мнение об их отсутствии
+- [Сравнение равенства и разницы (diffs)](#types-of-equality)
+- [Печать разниц (diffs)](#print-diffs)
+- Подробнее о различии между тестовыми помощниками и помощниками утверждений
+ см. [лучшие практики](https://neonxp.ru/pages/gostyleguide/google/best-practices/#test-functions)
+- Раздел [Go FAQ] о [фреймворках тестирования] и их мнение об их отсутствии
[полезные сообщения об ошибках]: #useful-test-failures
[`fmt`]: https://golang.org/pkg/fmt/
@@ -3136,7 +3111,7 @@ func TestBlogPost_VeritableRant(t *testing.T) {
предпочитайте использовать слова "got" и "want" соответственно.
Для разниц (diffs) направленность менее очевидна, и поэтому важно включить ключ,
-чтобы помочь в интерпретации неудачи. См. [раздел о печати разниц]. Независимо
+чтобы помочь в интерпретации неудачи. См. [раздел о печати разниц]. Независимо
от порядка diff, который вы используете в своих сообщениях об ошибках, вы должны
явно указать его как часть сообщения об ошибке, поскольку существующий код
непоследователен в порядке.
@@ -3186,8 +3161,7 @@ if tail != `Fran & Freddie's Diner"` {
[глубокого сравнения (deep comparison)]: #types-of-equality
[`cmpopts`]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts
-[`cmpopts.IgnoreInterfaces`]:
- https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts#IgnoreInterfaces
+[`cmpopts.IgnoreInterfaces`]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts#IgnoreInterfaces
<a id="compare-stable-results"></a>
@@ -3239,7 +3213,7 @@ if diff := cmp.Diff(wantVariance, gotVariance); diff != "" {
Вызов `t.Fatal` в первую очередь полезен для сообщения о неожиданном условии
(таком как ошибка или несоответствие вывода), когда последующие неудачи были бы
бессмысленны или даже вводили бы исследователя в заблуждение. Обратите внимание,
-как код ниже вызывает `t.Fatalf` и *затем* `t.Errorf`:
+как код ниже вызывает `t.Fatalf` и _затем_ `t.Errorf`:
```go
// Хорошо:
@@ -3259,10 +3233,10 @@ if gotDecoded != input {
Для табличных тестов рассмотрите использование подтестов и используйте `t.Fatal`
вместо `t.Error` и `continue`. См. также [GoTip #25: Subtests: Making Your Tests
-Lean](https://google.github.io/styleguide/go/index.html#gotip).
+Lean](/pages/gostyleguide/google/index.html#gotip).
**Лучшая практика:** Для дальнейшего обсуждения о том, когда следует
-использовать `t.Fatal`, см. [лучшие практики](https://neonxp.ru/pages/gostyleguide/google/best-practices/#t-fatal).
+использовать `t.Fatal`, см. [лучшие практики](https://neonxp.ru/pages/gostyleguide/google/best-practices/#t-fatal).
<a id="types-of-equality"></a>
@@ -3307,30 +3281,29 @@ if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" {
Хотя пакет `cmp` не является частью стандартной библиотеки Go, он поддерживается
командой Go и должен обеспечивать стабильные результаты равенства с течением
-времени. Он настраивается пользователем и должен удовлетворять большинству
+времени. Он настраивается пользователем и должен удовлетворять большинству
потребностей в сравнении.
[определенные языком сравнения]: http://golang.org/ref/spec#Comparison_operators
[`cmp`]: https://pkg.go.dev/github.com/google/go-cmp/cmp
[`cmp.Equal`]: https://pkg.go.dev/github.com/google/go-cmp/cmp#Equal
[`cmp.Diff`]: https://pkg.go.dev/github.com/google/go-cmp/cmp#Diff
-[`protocmp.Transform`]:
- https://pkg.go.dev/google.golang.org/protobuf/testing/protocmp#Transform
+[`protocmp.Transform`]: https://pkg.go.dev/google.golang.org/protobuf/testing/protocmp#Transform
Существующий код может использовать следующие более старые библиотеки и может
продолжать использовать их для согласованности:
-* [`pretty`] создает эстетически приятные отчеты о различиях. Однако он
- довольно намеренно считает значения, имеющие одинаковое визуальное
- представление, равными. В частности, `pretty` не улавливает различия между
- nil срезами и пустыми, не чувствителен к разным реализациям интерфейсов с
- идентичными полями, и возможно использовать вложенную карту в качестве
- основы для сравнения со значением структуры. Он также сериализует все
- значение в строку перед созданием diff, и, как таковой, не является хорошим
- выбором для сравнения больших значений. По умолчанию он сравнивает
- неэкспортируемые поля, что делает его чувствительным к изменениям в деталях
- реализации в ваших зависимостях. По этой причине нецелесообразно
- использовать `pretty` на сообщениях protobuf.
+- [`pretty`] создает эстетически приятные отчеты о различиях. Однако он
+ довольно намеренно считает значения, имеющие одинаковое визуальное
+ представление, равными. В частности, `pretty` не улавливает различия между
+ nil срезами и пустыми, не чувствителен к разным реализациям интерфейсов с
+ идентичными полями, и возможно использовать вложенную карту в качестве
+ основы для сравнения со значением структуры. Он также сериализует все
+ значение в строку перед созданием diff, и, как таковой, не является хорошим
+ выбором для сравнения больших значений. По умолчанию он сравнивает
+ неэкспортируемые поля, что делает его чувствительным к изменениям в деталях
+ реализации в ваших зависимостях. По этой причине нецелесообразно
+ использовать `pretty` на сообщениях protobuf.
[`pretty`]: https://pkg.go.dev/github.com/kylelemons/godebug/pretty
@@ -3344,7 +3317,7 @@ if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" {
быть обновлен до одной из вышеупомянутых библиотек.
**Примечание:** Пакет `cmp` предназначен для тестирования, а не для
-использования в продакшене. Как таковой, он может вызывать панику, когда
+использования в продакшене. Как таковой, он может вызывать панику, когда
подозревает, что сравнение выполнено неправильно, чтобы дать инструкции
пользователям, как улучшить тест, чтобы он был менее хрупким. Учитывая
склонность cmp к панике, он непригоден для кода, который используется в
@@ -3358,19 +3331,19 @@ if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" {
`YourFunc(%v) = %v, want %v`. Однако бывают случаи, которые могут потребовать
больше или меньше деталей:
-* Тесты, выполняющие сложные взаимодействия, должны также описывать
- взаимодействия. Например, если один и тот же `YourFunc` вызывается
- несколько раз, идентифицируйте, какой вызов провалил тест. Если важно знать
- любое дополнительное состояние системы, включите это в вывод ошибки (или
- хотя бы в логи).
-* Если данные представляют собой сложную структуру со значительным шаблонным
- кодом, допустимо описать только важные части в сообщении, но не чрезмерно
- затемняйте данные.
-* Ошибки настройки не требуют такого же уровня детализации. Если тестовый
- помощник заполняет таблицу Spanner, но Spanner был выключен, вам, вероятно,
- не нужно включать, какие тестовые входные данные вы собирались сохранить в
- базе данных. `t.Fatalf("Setup: Failed to set up test database: %s", err)`
- обычно достаточно полезно, чтобы решить проблему.
+- Тесты, выполняющие сложные взаимодействия, должны также описывать
+ взаимодействия. Например, если один и тот же `YourFunc` вызывается
+ несколько раз, идентифицируйте, какой вызов провалил тест. Если важно знать
+ любое дополнительное состояние системы, включите это в вывод ошибки (или
+ хотя бы в логи).
+- Если данные представляют собой сложную структуру со значительным шаблонным
+ кодом, допустимо описать только важные части в сообщении, но не чрезмерно
+ затемняйте данные.
+- Ошибки настройки не требуют такого же уровня детализации. Если тестовый
+ помощник заполняет таблицу Spanner, но Spanner был выключен, вам, вероятно,
+ не нужно включать, какие тестовые входные данные вы собирались сохранить в
+ базе данных. `t.Fatalf("Setup: Failed to set up test database: %s", err)`
+ обычно достаточно полезно, чтобы решить проблему.
**Совет:** Заставьте ваш режим отказа срабатывать во время разработки.
Просмотрите, как выглядит сообщение об ошибке, и может ли сопровождающий
@@ -3379,11 +3352,11 @@ if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" {
Существуют некоторые методы для ясного воспроизведения тестовых входов и
выходов:
-* При выводе строковых данных [`%q` часто полезен](#use-percent-q) для
- выделения важности значения и более легкого обнаружения плохих значений.
-* При выводе (маленьких) структур `%+v` может быть полезнее, чем `%v`.
-* Когда проверка больших значений завершается неудачей, [печать разницы
- (diff)](#print-diffs) может облегчить понимание неудачи.
+- При выводе строковых данных [`%q` часто полезен](#use-percent-q) для
+ выделения важности значения и более легкого обнаружения плохих значений.
+- При выводе (маленьких) структур `%+v` может быть полезнее, чем `%v`.
+- Когда проверка больших значений завершается неудачей, [печать разницы
+ (diff)](#print-diffs) может облегчить понимание неудачи.
<a id="print-diffs"></a>
@@ -3398,9 +3371,9 @@ if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" {
См. [типы равенства] для рекомендаций относительно сильных и слабых сторон
каждой функции.
-* [`cmp.Diff`]
+- [`cmp.Diff`]
-* [`pretty.Compare`]
+- [`pretty.Compare`]
Вы можете использовать пакет [`diff`] для сравнения многострочных строк или
списков строк. Вы можете использовать это как строительный блок для других видов
@@ -3408,8 +3381,7 @@ if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" {
[типы равенства]: #types-of-equality
[`diff`]: https://pkg.go.dev/github.com/kylelemons/godebug/diff
-[`pretty.Compare`]:
- https://pkg.go.dev/github.com/kylelemons/godebug/pretty#Compare
+[`pretty.Compare`]: https://pkg.go.dev/github.com/kylelemons/godebug/pretty#Compare
Добавьте некоторый текст в ваше сообщение об ошибке, объясняющий направление
diff.
@@ -3423,17 +3395,17 @@ order to use is also intentional, as there is no consensus which is
-->
-* Что-то вроде `diff (-want +got)` хорошо, когда вы используете пакеты `cmp`,
- `pretty` и `diff` (если вы передаете `(want, got)` в функцию), потому что
- `-` и `+`, которые вы добавляете в строку формата, будут соответствовать `-`
- и `+`, которые фактически появляются в начале строк diff. Если вы передаете
- `(got, want)` в вашу функцию, правильным ключом будет `(-got +want)` вместо
- этого.
+- Что-то вроде `diff (-want +got)` хорошо, когда вы используете пакеты `cmp`,
+ `pretty` и `diff` (если вы передаете `(want, got)` в функцию), потому что
+ `-` и `+`, которые вы добавляете в строку формата, будут соответствовать `-`
+ и `+`, которые фактически появляются в начале строк diff. Если вы передаете
+ `(got, want)` в вашу функцию, правильным ключом будет `(-got +want)` вместо
+ этого.
-* Пакет `messagediff` использует другой формат вывода, поэтому сообщение `diff
- (want -> got)` уместно, когда вы его используете (если вы передаете `(want,
- got)` в функцию), потому что направление стрелки будет соответствовать
- направлению стрелки в строках "modified".
+- Пакет `messagediff` использует другой формат вывода, поэтому сообщение `diff
+(want -> got)` уместно, когда вы его используете (если вы передаете `(want,
+got)` в функцию), потому что направление стрелки будет соответствовать
+ направлению стрелки в строках "modified".
Diff будет занимать несколько строк, поэтому вы должны напечатать новую строку
перед печатью diff.
@@ -3458,7 +3430,7 @@ Diff будет занимать несколько строк, поэтому
Тесты должны стремиться тестировать только семантическую информацию, которую
можно надежно наблюдать, а не отображаемую информацию, предназначенную для
отладки человеком, поскольку последняя часто подвержена будущим изменениям.
-Рекомендации по созданию ошибок со смысловым значением см. [лучшие практики
+Рекомендации по созданию ошибок со смысловым значением см. [лучшие практики
относительно ошибок](https://neonxp.ru/pages/gostyleguide/google/best-practices/#error-handling). Если ошибка с недостаточной
семантической информацией исходит из зависимости вне вашего контроля,
рассмотрите возможность создания отчета об ошибке (bug) владельцу, чтобы помочь
@@ -3485,12 +3457,10 @@ Diff будет занимать несколько строк, поэтому
> ```
См. также [GoTip #13: Designing Errors for
-Checking](https://google.github.io/styleguide/go/index.html#gotip).
+Checking](/pages/gostyleguide/google/index.html#gotip).
-[tott-350]:
- https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html
-[`cmpopts.EquateErrors`]:
- https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts#EquateErrors
+[tott-350]: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html
+[`cmpopts.EquateErrors`]: https://pkg.go.dev/github.com/google/go-cmp/cmp/cmpopts#EquateErrors
[`errors.Is`]: https://pkg.go.dev/errors#Is
<a id="test-structure"></a>
@@ -3503,8 +3473,8 @@ Checking](https://google.github.io/styleguide/go/index.html#gotip).
Стандартная библиотека тестирования Go предоставляет возможность [определять
подтесты]. Это позволяет гибкость в настройке и очистке, управлении
-параллелизмом и фильтрации тестов. Подтесты могут быть полезны (особенно для
-табличных тестов), но их использование не обязательно. См. также [пост в блоге
+параллелизмом и фильтрации тестов. Подтесты могут быть полезны (особенно для
+табличных тестов), но их использование не обязательно. См. также [пост в блоге
Go о подтестах](https://blog.golang.org/subtests).
Подтесты не должны зависеть от выполнения других случаев для успеха или
@@ -3512,8 +3482,7 @@ Go о подтестах](https://blog.golang.org/subtests).
индивидуально с использованием флагов `go test -run` или выражений [фильтра
тестов] Bazel.
-[определять подтесты]:
- https://pkg.go.dev/testing#hdr-Subtests_and_Sub_benchmarks
+[определять подтесты]: https://pkg.go.dev/testing#hdr-Subtests_and_Sub_benchmarks
[фильтра тестов]: https://bazel.build/docs/user-manual#test-filter
<a id="subtest-names"></a>
@@ -3523,9 +3492,9 @@ Go о подтестах](https://blog.golang.org/subtests).
Назовите ваш подтест так, чтобы он был читаем в выводе теста и полезен в
командной строке для пользователей фильтрации тестов. Когда вы используете
`t.Run` для создания подтеста, первый аргумент используется как описательное имя
-для теста. Чтобы гарантировать, что результаты тестов читаемы для людей,
+для теста. Чтобы гарантировать, что результаты тестов читаемы для людей,
читающих логи, выбирайте имена подтестов, которые останутся полезными и
-читаемыми после экранирования. Думайте об именах подтестов скорее как об
+читаемыми после экранирования. Думайте об именах подтестов скорее как об
идентификаторе функции, чем о прозаическом описании.
Тестовый раннер заменяет пробелы подчеркиваниями и экранирует непечатаемые
@@ -3591,12 +3560,11 @@ t.Run("AM/PM confusion", ...)
```
См. также [Go Tip #117: Subtest
-Names](https://google.github.io/styleguide/go/index.html#gotip).
+Names](/pages/gostyleguide/google/index.html#gotip).
[Go test runner]: https://golang.org/cmd/go/#hdr-Testing_flags
[идентифицировать входные данные]: #identify-the-input
-[особое значение для фильтров тестов]:
- https://blog.golang.org/subtests#:~:text=Perhaps%20a%20bit,match%20any%20tests
+[особое значение для фильтров тестов]: https://blog.golang.org/subtests#:~:text=Perhaps%20a%20bit,match%20any%20tests
<a id="table-driven-tests"></a>
@@ -3605,19 +3573,17 @@ Names](https://google.github.io/styleguide/go/index.html#gotip).
Используйте табличные тесты, когда множество различных тестовых случаев могут
быть протестированы с помощью сходной тестовой логики.
-* При тестировании того, равен ли фактический вывод функции ожидаемому выводу.
- Например, множество [тестов `fmt.Sprintf`] или минимальный фрагмент ниже.
-* При тестировании того, соответствуют ли выводы функции всегда одному и тому
- же набору инвариантов. Например, [тесты для `net.Dial`].
+- При тестировании того, равен ли фактический вывод функции ожидаемому выводу.
+ Например, множество [тестов `fmt.Sprintf`] или минимальный фрагмент ниже.
+- При тестировании того, соответствуют ли выводы функции всегда одному и тому
+ же набору инвариантов. Например, [тесты для `net.Dial`].
-[тестов `fmt.Sprintf`]:
- https://cs.opensource.google/go/go/+/master:src/fmt/fmt_test.go
-[тестов для `net.Dial`]:
- https://cs.opensource.google/go/go/+/master:src/net/dial_test.go;l=318;drc=5b606a9d2b7649532fe25794fa6b99bd24e7697c
+[тестов `fmt.Sprintf`]: https://cs.opensource.google/go/go/+/master:src/fmt/fmt_test.go
+[тестов для `net.Dial`]: https://cs.opensource.google/go/go/+/master:src/net/dial_test.go;l=318;drc=5b606a9d2b7649532fe25794fa6b99bd24e7697c
Вот минимальная структура табличного теста. При необходимости вы можете
использовать другие имена или добавить дополнительные средства, такие как
-подтесты или функции настройки и очистки. Всегда помните о [полезных сообщениях
+подтесты или функции настройки и очистки. Всегда помните о [полезных сообщениях
об ошибках тестов](#useful-test-failures).
```go
@@ -3664,7 +3630,7 @@ func TestCompare(t *testing.T) {
Когда дополнительные тестовые случаи просты (например, базовая проверка ошибок)
и не вводят условный поток кода в теле цикла табличного теста, допустимо
включить этот случай в существующий тест, хотя будьте осторожны, используя такую
-логику. То, что начинается просто сегодня, может органически вырасти во что-то
+логику. То, что начинается просто сегодня, может органически вырасти во что-то
неподдерживаемое.
Например:
@@ -3727,8 +3693,7 @@ func TestDivide(t *testing.T) {
лучшим подходом является написание двух отдельных табличных тестовых функций:
одну для обычных не-ошибочных выводов, и одну для ошибочных выводов.
-[GoTip #50: Disjoint Table Tests]:
- https://google.github.io/styleguide/go/index.html#gotip
+[GoTip #50: Disjoint Table Tests]: /pages/gostyleguide/google/index.html#gotip
<a id="table-tests-data-driven"></a>
@@ -3860,7 +3825,7 @@ for i, d := range tests {
```
Добавьте описание теста в вашу тестовую структуру и печатайте его вместе с
-сообщениями об ошибках. При использовании подтестов имя вашего подтеста должно
+сообщениями об ошибках. При использовании подтестов имя вашего подтеста должно
эффективно идентифицировать строку.
**Важно:** Хотя `t.Run` ограничивает область вывода и выполнения, вы должны
@@ -3874,7 +3839,7 @@ for i, d := range tests {
### Тестовые помощники (Test helpers)
-Тестовый помощник — это функция, выполняющая задачу настройки или очистки. Все
+Тестовый помощник — это функция, выполняющая задачу настройки или очистки. Все
ошибки, возникающие в тестовых помощниках, должны быть ошибками окружения (а не
кода под тестом) — например, когда тестовая база данных не может быть запущена
потому что на этой машине не осталось свободных портов.
@@ -3930,9 +3895,9 @@ func readFile(t *testing.T, filename string) string {
Чтобы написать тест в том же пакете:
-* Поместите тесты в файл `foo_test.go`
-* Используйте `package foo` для тестового файла
-* Не импортируйте явно тестируемый пакет
+- Поместите тесты в файл `foo_test.go`
+- Используйте `package foo` для тестового файла
+- Не импортируйте явно тестируемый пакет
```build
# Хорошо:
@@ -3956,12 +3921,11 @@ go_test(
```
Тест в том же пакете может обращаться к неэкспортированным идентификаторам в
-пакете. Это может обеспечить лучшее покрытие тестами и более лаконичные тесты.
+пакете. Это может обеспечить лучшее покрытие тестами и более лаконичные тесты.
Имейте в виду, что любые [примеры], объявленные в тесте, не будут иметь имен
пакетов, которые понадобятся пользователю в их коде.
-[`library`]:
- https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_library
+[`library`]: https://github.com/bazelbuild/rules_go/blob/master/docs/go/core/rules.md#go_library
[примеры]: #examples
<a id="test-different-package"></a>
@@ -3969,12 +3933,12 @@ go_test(
#### Тесты в другом пакете
Не всегда уместно или даже возможно определить тест в том же пакете, что и
-тестируемый код. В этих случаях используйте имя пакета с суффиксом `_test`. Это
+тестируемый код. В этих случаях используйте имя пакета с суффиксом `_test`. Это
исключение из правила "без подчеркиваний" для [имен пакетов](#package-names).
Например:
-* Если интеграционный тест не имеет очевидной библиотеки, к которой он
- принадлежит
+- Если интеграционный тест не имеет очевидной библиотеки, к которой он
+ принадлежит
```go
// Хорошо:
@@ -3983,7 +3947,7 @@ go_test(
import "testing"
```
-* Если определение тестов в том же пакете приводит к циклическим зависимостям
+- Если определение тестов в том же пакете приводит к циклическим зависимостям
```go
// Хорошо:
@@ -4007,12 +3971,12 @@ go_test(
Пакет `testing` предоставляет минимальный, но полный набор функциональности для
написания хороших тестов:
-* Тесты верхнего уровня
-* Бенчмарки
-* [Исполняемые примеры](https://blog.golang.org/examples)
-* Подтесты
-* Логирование
-* Ошибки и фатальные ошибки
+- Тесты верхнего уровня
+- Бенчмарки
+- [Исполняемые примеры](https://blog.golang.org/examples)
+- Подтесты
+- Логирование
+- Ошибки и фатальные ошибки
Они разработаны для слаженной работы с основными языковыми возможностями, такими
как [составные литералы] и [if с инициализатором], чтобы позволить авторам
@@ -4031,17 +3995,17 @@ go_test(
мнения. Тем не менее, вот несколько вещей, по которым сообщество читаемости
ранее спорило и не достигло консенсуса.
-* **Локальная инициализация переменных нулевым значением**. `var i int` и `i
- := 0` эквивалентны. См. также [лучшие практики инициализации].
-* **Пустой составной литерал vs. `new` или `make`**. `&File{}` и `new(File)`
- эквивалентны. Так же `map[string]bool{}` и `make(map[string]bool)`. См.
- также [лучшие практики составных объявлений].
-* **Порядок аргументов got, want в вызовах cmp.Diff**. Будьте локально
- последовательны и [включите легенду](#print-diffs) в ваше сообщение об
- ошибке.
-* **`errors.New` vs `fmt.Errorf` на неформатированных строках**.
- `errors.New("foo")` и `fmt.Errorf("foo")` могут использоваться
- взаимозаменяемо.
+- **Локальная инициализация переменных нулевым значением**. `var i int` и `i
+:= 0` эквивалентны. См. также [лучшие практики инициализации].
+- **Пустой составной литерал vs. `new` или `make`**. `&File{}` и `new(File)`
+ эквивалентны. Так же `map[string]bool{}` и `make(map[string]bool)`. См.
+ также [лучшие практики составных объявлений].
+- **Порядок аргументов got, want в вызовах cmp.Diff**. Будьте локально
+ последовательны и [включите легенду](#print-diffs) в ваше сообщение об
+ ошибке.
+- **`errors.New` vs `fmt.Errorf` на неформатированных строках**.
+ `errors.New("foo")` и `fmt.Errorf("foo")` могут использоваться
+ взаимозаменяемо.
Если возникнут особые обстоятельства, наставник по читаемости может сделать
необязательный комментарий, но в целом автор волен выбирать предпочитаемый им
@@ -4051,7 +4015,5 @@ go_test(
дополнительного обсуждения, авторы могут спросить — либо в конкретном ревью,
либо на внутренних досках сообщений.
-[лучшие практики составных объявлений]:
- https://google.github.io/styleguide/go/best-practices#vardeclcomposite
-[лучшие практики инициализации]:
- https://google.github.io/styleguide/go/best-practices#vardeclinitialization
+[лучшие практики составных объявлений]: /pages/gostyleguide/google/best-practices#vardeclcomposite
+[лучшие практики инициализации]: /pages/gostyleguide/google/best-practices#vardeclinitialization
diff --git a/content/pages/gostyleguide/google/guide.md b/content/pages/gostyleguide/google/guide.md
index 31b3b33..e22a8aa 100644
--- a/content/pages/gostyleguide/google/guide.md
+++ b/content/pages/gostyleguide/google/guide.md
@@ -1,16 +1,12 @@
---
-order: 3
-title: Google Go Style Guide — Руководство
+weight: 10
+title: Руководство по стилю Go
---
# Руководство по стилю Go (Go Style Guide)
Оригинал: https://google.github.io/styleguide/go/guide
-[Обзор](https://neonxp.ru/pages/gostyleguide/google/) | [Руководство](https://neonxp.ru/pages/gostyleguide/google/guide) | [Решения](https://neonxp.ru/pages/gostyleguide/google/decisions) |
-[Лучшие практики](https://neonxp.ru/pages/gostyleguide/google/best-practices)
-
-
**Примечание:** Это часть серии документов, описывающих [Стиль Go (Go
Style)](https://neonxp.ru/pages/gostyleguide/google/) в Google. Данный документ является **[нормативным
(normative)](https://neonxp.ru/pages/gostyleguide/google/#normative) и [каноническим (canonical)](https://neonxp.ru/pages/gostyleguide/google/#canonical)**.
@@ -52,8 +48,8 @@ Style)](https://neonxp.ru/pages/gostyleguide/google/) в Google. Данный д
Важнее, чтобы код был легок для чтения, а не для написания. Понятность кода
имеет два аспекта:
-* [Что именно делает код?](#clarity-purpose)
-* [Почему код делает то, что он делает?](#clarity-rationale)
+- [Что именно делает код?](#clarity-purpose)
+- [Почему код делает то, что он делает?](#clarity-rationale)
<a id="clarity-purpose"></a>
@@ -64,10 +60,10 @@ Go разработан таким образом, чтобы относител
предварительные знания для понимания кода, стоит потратить время, чтобы сделать
цель кода более ясной для будущих читателей. Например, может помочь:
-* Использование более описательных имен переменных
-* Добавление дополнительных комментариев
-* Разделение кода пробелами и комментариями
-* Рефакторинг кода в отдельные функции/методы для повышения модульности
+- Использование более описательных имен переменных
+- Добавление дополнительных комментариев
+- Разделение кода пробелами и комментариями
+- Рефакторинг кода в отдельные функции/методы для повышения модульности
Здесь нет универсального решения, но при разработке кода на Go важно отдавать
приоритет понятности.
@@ -81,10 +77,10 @@ Go разработан таким образом, чтобы относител
особенно важно, когда код содержит нюансы, с которыми читатель может быть не
знаком, например:
-* Нюанс языка, например, замыкание захватит переменную цикла, но само
- замыкание находится далеко от него
-* Нюанс бизнес-логики, например, проверка прав доступа, которая должна
- различать реального пользователя и того, кто выдает себя за пользователя
+- Нюанс языка, например, замыкание захватит переменную цикла, но само
+ замыкание находится далеко от него
+- Нюанс бизнес-логики, например, проверка прав доступа, которая должна
+ различать реального пользователя и того, кто выдает себя за пользователя
API может требовать осторожного использования. Например, фрагмент кода может
быть сложным и трудным для понимания из-за соображений производительности, или
@@ -99,8 +95,8 @@ API может требовать осторожного использован
беспорядок, пересказывая то, что код уже говорит, противореча коду или добавляя
нагрузку по поддержке актуальности комментариев. Позвольте коду говорить самому
за себя (например, делая имена символов самодокументированными), а не добавляйте
-избыточные комментарии. Зачастую лучше, чтобы комментарии объясняли, *почему*
-что-то сделано, а не *что* делает код.
+избыточные комментарии. Зачастую лучше, чтобы комментарии объясняли, _почему_
+что-то сделано, а не _что_ делает код.
Кодовая база Google в значительной степени единообразна и согласована. Часто
бывает, что код, который выделяется (например, использованием незнакомого
@@ -111,16 +107,16 @@ API может требовать осторожного использован
Стандартная библиотека содержит множество примеров реализации этого принципа.
Среди них:
-* Комментарии сопровождающих в [`package
- sort`](https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/sort/sort.go).
-* Хорошие [запускаемые примеры в том же
- пакете](https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/sort/example_search_test.go),
- которые полезны как пользователям (они [отображаются в
- godoc](https://pkg.go.dev/sort#pkg-examples)), так и сопровождающим (они
- [запускаются как часть тестов](https://neonxp.ru/pages/gostyleguide/google/decisions/#examples)).
-* [`strings.Cut`](https://pkg.go.dev/strings#Cut) — это всего четыре строки
- кода, но они повышают [понятность и корректность мест вызова
- (callsites)](https://github.com/golang/go/issues/46336).
+- Комментарии сопровождающих в [`package
+sort`](https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/sort/sort.go).
+- Хорошие [запускаемые примеры в том же
+ пакете](https://cs.opensource.google/go/go/+/refs/tags/go1.19.2:src/sort/example_search_test.go),
+ которые полезны как пользователям (они [отображаются в
+ godoc](https://pkg.go.dev/sort#pkg-examples)), так и сопровождающим (они
+ [запускаются как часть тестов](https://neonxp.ru/pages/gostyleguide/google/decisions/#examples)).
+- [`strings.Cut`](https://pkg.go.dev/strings#Cut) — это всего четыре строки
+ кода, но они повышают [понятность и корректность мест вызова
+ (callsites)](https://github.com/golang/go/issues/46336).
<a id="simplicity"></a>
@@ -133,17 +129,17 @@ API может требовать осторожного использован
как с точки зрения поведения, так и производительности. Внутри кодовой базы Go в
Google простой код:
-* Легко читается сверху вниз
-* Не предполагает, что вы уже знаете, что он делает
-* Не предполагает, что вы можете запомнить весь предшествующий код
-* Не имеет ненужных уровней абстракции
-* Не имеет имен, которые привлекают внимание к чему-то обыденному
-* Делает передачу значений и принятие решений понятными для читателя
-* Имеет комментарии, которые объясняют *почему*, а не *что* делает код, чтобы
- избежать будущих отклонений
-* Имеет самодостаточную документацию
-* Имеет полезные ошибки и полезные сообщения об ошибках в тестах
-* Часто может быть взаимоисключающим с "умным" кодом
+- Легко читается сверху вниз
+- Не предполагает, что вы уже знаете, что он делает
+- Не предполагает, что вы можете запомнить весь предшествующий код
+- Не имеет ненужных уровней абстракции
+- Не имеет имен, которые привлекают внимание к чему-то обыденному
+- Делает передачу значений и принятие решений понятными для читателя
+- Имеет комментарии, которые объясняют _почему_, а не _что_ делает код, чтобы
+ избежать будущих отклонений
+- Имеет самодостаточную документацию
+- Имеет полезные ошибки и полезные сообщения об ошибках в тестах
+- Часто может быть взаимоисключающим с "умным" кодом
Могут возникать компромиссы между простотой кода и простотой использования API.
Например, может иметь смысл сделать код более сложным, чтобы конечному
@@ -219,11 +215,11 @@ Google простой код:
Многое может помешать выделению наиболее важных деталей в любой момент:
-* Повторяющийся код
-* Лишний синтаксис
-* [Непонятные имена](#naming)
-* Ненужная абстракция
-* Пробелы
+- Повторяющийся код
+- Лишний синтаксис
+- [Непонятные имена](#naming)
+- Ненужная абстракция
+- Пробелы
Повторяющийся код особенно затмевает различия между каждым почти идентичным
разделом и требует от читателя визуального сравнения похожих строк кода, чтобы
@@ -258,8 +254,7 @@ if err := doSomething(); err == nil { // если ошибки НЕТ
}
```
-[Табличное тестирование (Table-driven testing)]:
- https://github.com/golang/go/wiki/TableDrivenTests
+[Табличное тестирование (Table-driven testing)]: https://github.com/golang/go/wiki/TableDrivenTests
[обработке ошибок (error handling)]: https://go.dev/blog/errors-are-values
["усилить" сигнал]: best-practices#signal-boost
@@ -273,15 +268,15 @@ if err := doSomething(); err == nil { // если ошибки НЕТ
Поддерживаемый код:
-* Легко модифицируется будущим программистом правильно
-* Имеет API, структурированные таким образом, что они могут элегантно
- развиваться
-* Четко указывает предположения, которые он делает, и выбирает абстракции,
- которые соответствуют структуре проблемы, а не структуре кода
-* Избегает ненужной связности и не включает неиспользуемые функции
-* Имеет комплексный набор тестов, чтобы гарантировать сохранение заявленного
- поведения и корректность важной логики, а тесты предоставляют четкие,
- действенные диагностические сообщения в случае неудачи
+- Легко модифицируется будущим программистом правильно
+- Имеет API, структурированные таким образом, что они могут элегантно
+ развиваться
+- Четко указывает предположения, которые он делает, и выбирает абстракции,
+ которые соответствуют структуре проблемы, а не структуре кода
+- Избегает ненужной связности и не включает неиспользуемые функции
+- Имеет комплексный набор тестов, чтобы гарантировать сохранение заявленного
+ поведения и корректность важной логики, а тесты предоставляют четкие,
+ действенные диагностические сообщения в случае неудачи
При использовании абстракций, таких как интерфейсы и типы, которые по
определению удаляют информацию из контекста, в котором они используются, важно
@@ -397,12 +392,11 @@ leap := leap4 && (!leap100 || leap400)
Все исходные файлы Go должны соответствовать формату, выводимому инструментом
`gofmt`. Этот формат обеспечивается проверкой перед отправкой (presubmit check)
-в кодовой базе Google. [Сгенерированный код] также обычно должен
+в кодовой базе Google. [Сгенерированный код] также обычно должен
форматироваться (например, с использованием [`format.Source`]), так как он также
просматривается в Code Search.
-[Сгенерированный код]:
- https://docs.bazel.build/versions/main/be/general.html#genrule
+[Сгенерированный код]: https://docs.bazel.build/versions/main/be/general.html#genrule
[`format.Source`]: https://pkg.go.dev/go/format#Source
<a id="mixed-caps"></a>
@@ -436,11 +430,11 @@ case) вместо подчеркиваний (змеиный регистр, sn
Не разделяйте строку:
-* Перед [изменением отступа (indentation
- change)](https://neonxp.ru/pages/gostyleguide/google/decisions/#indentation-confusion) (например, объявление функции,
- условие)
-* Чтобы длинная строка (например, URL) поместилась в несколько более коротких
- строк
+- Перед [изменением отступа (indentation
+ change)](https://neonxp.ru/pages/gostyleguide/google/decisions/#indentation-confusion) (например, объявление функции,
+ условие)
+- Чтобы длинная строка (например, URL) поместилась в несколько более коротких
+ строк
<a id="naming"></a>
@@ -450,16 +444,15 @@ case) вместо подчеркиваний (змеиный регистр, sn
короче, чем во многих других языках, но применяются те же [общие принципы].
Имена должны:
-* Не казаться [избыточными (repetitive)](https://neonxp.ru/pages/gostyleguide/google/decisions/#repetition) при
- использовании
-* Учитывать контекст
-* Не повторять концепции, которые уже ясны
+- Не казаться [избыточными (repetitive)](https://neonxp.ru/pages/gostyleguide/google/decisions/#repetition) при
+ использовании
+- Учитывать контекст
+- Не повторять концепции, которые уже ясны
Более конкретные рекомендации по именованию можно найти в [решениях
(https://neonxp.ru/pages/gostyleguide/google/decisions/)](https://neonxp.ru/pages/gostyleguide/google/decisions/#naming).
-[общие принципы]:
- https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html
+[общие принципы]: https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html
<a id="local-consistency"></a>
@@ -473,13 +466,13 @@ case) вместо подчеркиваний (змеиный регистр, sn
Примеры **допустимых** соображений локального стиля:
-* Использование `%s` или `%v` для форматированного вывода ошибок
-* Использование буферизованных каналов вместо мьютексов
+- Использование `%s` или `%v` для форматированного вывода ошибок
+- Использование буферизованных каналов вместо мьютексов
Примеры **недопустимых** соображений локального стиля:
-* Ограничения на длину строк для кода
-* Использование библиотек тестирования на основе утверждений (assertion-based)
+- Ограничения на длину строк для кода
+- Использование библиотек тестирования на основе утверждений (assertion-based)
Если локальный стиль противоречит руководству по стилю, но влияние на читаемость
ограничено одним файлом, это обычно будет отмечено в ревью кода, для которого
@@ -492,4 +485,4 @@ case) вместо подчеркиваний (змеиный регистр, sn
допустимым обоснованием для нарушения руководства по стилю в новом коде. В этих
случаях автору уместно либо очистить существующую кодовую базу в том же CL, либо
выполнить рефакторинг перед текущим CL, либо найти альтернативу, которая, по
-крайней мере, не усугубляет локальную проблему. \ No newline at end of file
+крайней мере, не усугубляет локальную проблему.
diff --git a/content/pages/gostyleguide/google/main.md b/content/pages/gostyleguide/google/main.md
deleted file mode 100644
index b3714ee..0000000
--- a/content/pages/gostyleguide/google/main.md
+++ /dev/null
@@ -1,184 +0,0 @@
----
-order: 1
-title: Google Go Style Guide — Руководство
----
-
-## О руководстве
-
-<!--more -->
-
-Руководство по стилю Go и сопутствующие документы кодифицируют современные
-наилучшие подходы к написанию читаемого и идиоматичного кода на Go. Следование
-Руководству по стилю не является абсолютным требованием, и эти документы никогда
-не будут исчерпывающими. Наша цель — минимизировать неопределённость при
-написании читаемого кода на Go, чтобы новички в языке могли избежать
-распространённых ошибок. Руководство по стилю также служит для унификации
-рекомендаций по стилю, даваемых любым рецензентом кода Go в Google.
-
-| Документ | Ссылка | Основная аудитория | [Нормативный] | [Канонический] |
-| ------------------------ | ----------------------------------------------------- | ------------------------ | ------------- | -------------- |
-| **Руководство по стилю** | https://google.github.io/styleguide/go/guide | Все | Да | Да |
-| **Решения по стилю** | https://google.github.io/styleguide/go/decisions | Наставники по читаемости | Да | Нет |
-| **Лучшие практики** | https://google.github.io/styleguide/go/best-practices | Все заинтересованные | Нет | Нет |
-
-[Нормативный]: #нормативный
-[Канонический]: #канонический
-
-<a id="docs"></a>
-
-### Документы
-
-1. **[Руководство по стилю](https://google.github.io/styleguide/go/guide)**
- описывает основы стиля Go в Google. Этот документ является окончательным и
- служит основой для рекомендаций в «Решениях по стилю» и «Лучших практиках».
-
-1. **[Решения по стилю](https://google.github.io/styleguide/go/decisions)** —
- это более подробный документ, который суммирует решения по конкретным
- вопросам стиля и, где уместно, обсуждает обоснование этих решений.
-
- Эти решения могут иногда меняться на основе новых данных, новых возможностей
- языка, новых библиотек или возникающих паттернов, но не ожидается, что
- отдельные программисты Go в Google должны следить за актуальностью этого
- документа.
-
-1. **[Лучшие практики](https://google.github.io/styleguide/go/best-practices)**
- документируют некоторые паттерны, которые развивались со временем для
- решения общих задач, хорошо читаются и устойчивы к потребностям поддержки
- кода.
-
- Эти лучшие практики не являются каноническими, но программистам Go в Google
- рекомендуется использовать их там, где это возможно, для сохранения
- единообразия и согласованности кодовой базы.
-
-Эти документы призваны:
-
-- Согласовать набор принципов для оценки альтернативных стилей
-- Кодифицировать устоявшиеся вопросы стиля Go
-- Документировать и предоставить канонические примеры идиом Go
-- Документировать плюсы и минусы различных решений по стилю
-- Помочь минимизировать неожиданности при рецензировании читаемости кода Go
-- Помочь наставникам по читаемости использовать согласованную терминологию и
- рекомендации
-
-Эти документы **не** призваны:
-
-- Быть исчерпывающим списком замечаний, которые можно дать при рецензировании
- читаемости
-- Перечислять все правила, которые каждый должен помнить и всегда соблюдать
-- Заменять здравый смысл при использовании возможностей языка и стиля
-- Оправдывать масштабные изменения для устранения различий в стиле
-
-Всегда будут существовать различия между разными программистами Go и между
-кодовыми базами разных команд. Однако в интересах Google и Alphabet, чтобы наша
-кодовая база была как можно более согласованной. (Подробнее о согласованности
-см. [руководство](https://neonxp.ru/pages/gostyleguide/google/guide/#consistency)). В связи с этим не стесняйтесь вносить
-улучшения стиля по мере необходимости, но вам не нужно придираться к каждому
-нарушению Руководства по стилю, которое вы обнаружите. В частности, эти
-документы могут меняться со временем, и это не повод вызывать лишнюю суету в
-существующих кодовых базах; достаточно писать новый код, используя новейшие
-лучшие практики, и со временем устранять проблемы поблизости.
-
-Важно понимать, что вопросы стиля по своей природе субъективны и всегда
-сопряжены с компромиссами. Большая часть рекомендаций в этих документах
-субъективна, но, как и в случае с `gofmt`, в обеспечиваемом ими единообразии
-есть значительная ценность. Поэтому рекомендации по стилю не будут меняться без
-должного обсуждения, и программистам Go в Google рекомендуется следовать
-руководству по стилю, даже если они с чем-то не согласны.
-
-<a id="definitions"></a>
-
-## Определения
-
-Ниже приведены определения следующих слов, которые используются во всех
-документах по стилю:
-
-- **Канонический**: Устанавливает предписывающие и долговечные правила <a
- id="canonical"></a>
-
- В этих документах «канонический» используется для описания чего-либо, что
- считается стандартом, которому должен следовать весь код (старый и новый) и
- который не должен существенно меняться с течением времени. Принципы в
- канонических документах должны быть понятны как авторам, так и рецензентам,
- поэтому всё, что включается в канонический документ, должно соответствовать
- высоким стандартам. Как таковые, канонические документы обычно короче и
- предписывают меньше элементов стиля, чем неканонические документы.
-
- https://google.github.io/styleguide/go#canonical
-
-- **Нормативный**: Призван установить согласованность <a id="normative"></a>
-
- В этих документах «нормативный» используется для описания чего-либо, что
- является согласованным элементом стиля для использования рецензентами кода
- Go, чтобы предложения, терминология и обоснования были последовательными.
- Эти элементы могут меняться со временем, и эти документы будут отражать
- такие изменения, чтобы рецензенты могли оставаться последовательными и в
- курсе событий. От авторов кода на Go не ожидается знакомства с нормативными
- документами, но рецензенты будут часто использовать их в качестве
- справочного материала при проверке читаемости.
-
- https://google.github.io/styleguide/go#normative
-
-- **Идиоматичный**: Распространённый и знакомый <a id="idiomatic"></a>
-
- В этих документах «идиоматичный» используется для обозначения чего-либо, что
- широко распространено в коде на Go и стало знакомым паттерном, который легко
- узнать. В целом, идиоматичный паттерн следует предпочитать неидиоматичному,
- если оба служат одной цели в контексте, поскольку именно это будет наиболее
- знакомо читателям.
-
- https://google.github.io/styleguide/go#idiomatic
-
-<a id="references"></a>
-
-## Дополнительные ссылки
-
-Данное руководство предполагает, что читатель знаком с [Effective Go], поскольку
-оно обеспечивает общую основу для кода на Go во всём сообществе Go.
-
-Ниже приведены некоторые дополнительные ресурсы для тех, кто хочет
-самостоятельно изучить стиль Go, и для рецензентов, желающих предоставить в
-своих отзывах дополнительный контекст с ссылками. От участников процесса
-проверки читаемости Go не ожидается знакомства с этими ресурсами, но они могут
-упоминаться в качестве контекста при таких проверках.
-
-[Effective Go]: https://go.dev/doc/effective_go
-
-**Внешние ссылки**
-
-- [Спецификация языка Go](https://go.dev/ref/spec)
-- [Часто задаваемые вопросы по Go](https://go.dev/doc/faq)
-- [Модель памяти Go](https://go.dev/ref/mem)
-- [Структуры данных в Go](https://research.swtch.com/godata)
-- [Интерфейсы в Go](https://research.swtch.com/interfaces)
-- [Поговорки Go](https://go-proverbs.github.io/)
-
-- <a id="gotip"></a> Выпуски Go Tip — следите за обновлениями.
-
-- <a id="unit-testing-practices"></a> Практики модульного тестирования —
- следите за обновлениями.
-
-**Соответствующие статьи Testing-on-the-Toilet**
-
-- [TotT: Именование идентификаторов][tott-431]
-- [TotT: Тестирование состояния vs. Тестирование взаимодействий][tott-281]
-- [TotT: Эффективное тестирование][tott-324]
-- [TotT: Тестирование, основанное на рисках][tott-329]
-- [TotT: Детекторные тесты считаются вредными][tott-350]
-
-[tott-431]: https://testing.googleblog.com/2017/10/code-health-identifiernamingpostforworl.html
-[tott-281]: https://testing.googleblog.com/2013/03/testing-on-toilet-testing-state-vs.html
-[tott-324]: https://testing.googleblog.com/2014/05/testing-on-toilet-effective-testing.html
-[tott-329]: https://testing.googleblog.com/2014/05/testing-on-toilet-risk-driven-testing.html
-[tott-350]: https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html
-
-**Дополнительные внешние материалы**
-
-- [Go и догма](https://research.swtch.com/dogma)
-- [Меньше — значит экспоненциально
- больше](https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html)
-- [Воображение
- Эсмеральды](https://commandcenter.blogspot.com/2011/12/esmereldas-imagination.html)
-- [Регулярные выражения для синтаксического
- анализа](https://commandcenter.blogspot.com/2011/08/regular-expressions-in-lexing-and.html)
-- [Стиль Gofmt никому не нравится, но Gofmt нравится
- всем](https://www.youtube.com/watch?v=PAAkCSZUG1c&t=8m43s) (YouTube)