Comments 8
Почему в го так модно использовать односимвольные имена переменных?
// Хорошо:
func (c *Config) WriteDetail(w io.Writer) (int64, error)
Нет, не хорошо. Очень плохо.
Да, меня покусал с++ и я хочу this, который некоторыми санитайзерами запрещен. Ну да ладно. Но почему односимвольные переменные не запрещены?
Зачем их запрещать? Для этого нужны внятные, объективные аргументы.
Аргументы почему это хорошо:
В Go есть идеоматические названия для переменных. Посмотрите код стандартной библиотеки и увидьте как называются в ней Reader и Writer например. Go-программист видит "w" и ожидает там writer. Видит i и ожидает счётчик. Конфиг сюда же.
Длинна имени переменной может являться подсказкой по области видимости переменной. Чем больше кода использует эту переменную, тем длиннее и описательнее должно быть её название. И наоборот, если она объявляется в сигнатуре и используется 2 раза внутри функции из 5 строк - одна буква это хороший выбор.
Имя this - очевидно плохая практика. Оно по определению зависит от контекста, который мы вынуждены удерживать во внимании. Это не даёт ничего, но усложняет mental model нашего кода, а мы этого не хотим. Мы хотим чётко представлять в уме всю реализацию задачи от и до, со всеми нюансами, это и отличает инженерию от "просто кодинга".
Вот тут сильно не согласен. This внутри метода это во многих языках "ясно и понятно". Во внутренних контекстах ещё бывает closure как "that", что не вызывает никаких ментальных трудностей. А вот местное и часто сокращенное именование объекта в методе, часто усложняет когнитивное восприятие, и подсветка синтаксиса в ряде ИДЕ далеко не всегда улучшает ситуацию.. синенькое, желтенькое, беленькое .. в глаза пестрить начинает.
Но .. не холивара для. ИМХО. Продолжать спор не планирую. На вкус каждому нравятся свои фломастеры. ;)
Если серьезно, то именовать ресивер this - это плохая практика именно из-за семантики ресивера - thing.Func(args...)
это всего лишь синтаксический сахар над (T).Func(thing, args...)
. В терминах С++ это все статические функции, и абсолютно легально вызывать их с нулевым ресивером (оф дока даже несколько издевательски утверждает, что _как правило_ все функции прекрасно работают с нулевым ресивером, но на практике это скорей фантастика :) )
Перевод кем-то проверялся? Ссылки на gotip битые, потому что авторы оригинального codestyle ещё не сделали этот раздел.
Кодестайл - это замечательно. Кто-нибудь может подсказать где прочитать про недостатки ГО и его компилятора? Например:
Эскейп анализ. Где подробно описано что за 80 попугаев определяют предельный размер инлайнинга функции или метода? В частности, как факт вот это:
// концептуально правильнее себя обзывать this все же..
func (this *MyObject) SetOutput(w io.Writer) {
this.blocker.Lock()
this.out = w
this.blocker.Unlock()
}
Уже не инлайнится т.к. тут инлайнятся функции мьютекса. Обьяснение эскейп анализа таково: " инлайн Lock, Unlock приводит к стоимости метода больше 80, ни магу"
func (this *MyObject) SetOutput(w io.Writer) {
this.blocker.Lock()
defer this.blocker.Unlock()
this.out = w
}
Не инлайнит ни методы мьютекса ни сам метод, т.к. в нем присутствует .. defer. Эскейп анализ так и обьясняет: "есть дефер, ни магу инлайнить"
Однократно(!) вызываемая функция/метод не инлайнятся по тем же причинам! Привет "многоуровневый кровавый энтерпрайз" со своими хелперами, брокерами, сервисами и пр. многослойными ремаппингами proto туда-сюда-обратно.. "быстрый" язык говорите.. ;)
Глобал, заявленный на уровне пакета в ряде случаев точно также .. выкидывается в кучу, вместо того, чтобы занять "статическое распределение". Аналогично локальные переменные из контекста легко мигрируют в кучу, в т.ч. по причине "большого размера" ..
Динамическое создание данных .. слайс - это две аллокации: подкапотный массив и собственно структуру слайса. Строка .. а ведь она тоже имеет указатель и длину.. сколько аллокаций? А у мапы?
GC .. сколько времени исполнения выделено ДО его первого запуска? Что происходит, если горутина отработала шустрее? Мне так удавалось в бенчмарке раскручивать до мегабайта занимаемой памяти логером с аллокацией в 16 байт за проход..
Писатель канала все ещё (1.20) не способен узнать о закрытии канала.. Даже специально добавлено в документацию. В итого, лепим дополнительные каналы, иные методы взаимодействия, обрамляем всё это мьютексами.. Доколе? :)
И всё это обнаружено внезапно в версии 1.20..
Где можно почитать про все эти и другие "фичи" скрытые под капотом?
Писатель канала все ещё (1.20) не способен узнать о закрытии канала.. Даже специально добавлено в документацию. В итого, лепим дополнительные каналы, иные методы взаимодействия, обрамляем всё это мьютексами.. Доколе? :)
Зачем писателю канала нужно знать о закрытии канала, если именно писатель должен его закрывать?
Читаем:
Note: Only the sender should close a channel, never the receiver. Sending on a closed channel will cause a panic.
Пишем на Go как в Google. Лучшие практики — часть первая