Go шустрая, но отнюдь не панацея от всех бед. Java, c#, c++ и прочие тоже не пальцем деланные.
Если говорить именно о том, что с fasthttp будет сильно круче, то не уверен, несколько быстрее будет. Fasthttp выделяет намного меньше памяти и соответственно GC меньше съест. Правда код на нем, по личному опыту, трудно поддерживать: неинформативные ошибки, попытка почитать код приводит к чтению функций по 200-400 строк…
Бенчмарки можно посмотреть тут
Если бы map передавался по указателю, то в обоих бы примерах он менялся для вызвавшего функцию кода. Этого не происходит, потому что происходит передача по значению.
Как верно сказали ниже, map содержит указатель, но и он передается по значению.
Все так, за счет бакетов есть возможность расширяться без создания новой структуры map.
То же самое справедливо и в отношении каналов. Только с учетом того, что его вместимость мы определяем сразу и не можем поменять, не создавая новый канал.
Да! Странно, что автор статьи не исследовал вопрос, о котором решил писать.
Map — это структура, передается по значению. Собственно поэтому возможны вот такие вещи.
Согласен, но хорошо бы уточнить, какого размера в строках кода были те проекты, где перевод занял человеко-дни и участвовали ли QA в переводе проектов, или было большое покрытие тестами, или помолясь…
При большом легаси в несколько MLOC потребовалось значительное время на перевод. Сначала сделаны были git hooks с запретом на коммиты кода с несовместимыми с php7 конструкциями — иначе переводить проект, где код пишут сотни php программистов не представлялось возможным. После последовательный перевод кода на 7. Не скажу что много работы, но и не мало получилось. Определенную сложность доставили расширения, поменявшие свою версию — привалило работы для qa на тестирования функционала, связанного с этими расширениями. И баги находились.
В целом для большого проекта получился быстрый переход. Но конечно не человекодни.
Тот редкий миг, когда понимаешь, что в лоб решение на golang аккуратнее, чем js:
package main
import (
"bytes"
"fmt"
"strconv"
"time"
)
func print(ch <-chan string, delay time.Duration, done chan struct{}) {
for toPrint := range ch {
time.Sleep(delay)
fmt.Println(toPrint)
}
close(done)
}
const (
miss = "Miss"
kiss = "Kiss"
)
func main() {
printCh := make(chan string, 100)
doneCh := make(chan struct{})
buf := bytes.Buffer{}
go print(printCh, 50*time.Microsecond, doneCh)
for i := 1; i <= 100; i++ {
if i%3 == 0 {
buf.WriteString(miss)
}
if i%5 == 0 {
buf.WriteString(kiss)
}
if buf.Len() == 0 {
buf.WriteString(strconv.Itoa(i))
}
printCh <- buf.String()
buf.Reset()
}
close(printCh)
<-doneCh
}
На все около 7 минут ушло.
А по теме статьи — да, проблема есть, но я не понимаю, зачем давать такие задания после ознакомления с кодом кандидата. А это бывает, к сожалению, часто. Как и тестовые задания на несколько дней…
Ну проблемы нет, есть неверный материал в лекциях, в частности из-за непонимания того, что в go есть только передача по значению можно написать такой неверный код
Соглашусь. Только на низком уровне с этим есть сложности и при потребности в максимальной прроизводительности: иначе же можно спокойно жить с fmt sync.map и прочим, принимающим и отдающим interface{} и не столкнуться с проблемами, ни кода ни производительности.
Мне кажется, что желание дженериков везде и всегда, сродни преждевременной оптимизации или неоправданному расширению задачи: надо было сделать для одного типа, но программист пробует написать обобщенный код.
Дженерики нужны, конечно, кодогенерация не помогает всегда, да и код усложняет в разы, как и отладку сгенерированного кода. И в самой стандартной библиотеке она не используется, то есть это решение и разработчикам golang не сильно нравится.
Но да, дженерики не настолько важны в действительной жизни. Рабочий код пишется и без них.
Указатель не есть тоже самое, что ссылка.
Можно сделать указатель, но в функцию его передашь все равно по значению. С unsafe то же самое. Ну будет uintptr — это не ссылка, а вполне себе значение.
Во первых, мое почтение за большую работу. Сейчас это самый полный материал по Golang, по крайней мере, на русском языке.
Но для пробы посмотрел вторую лекцию и был удивлен: в лекции рассматриваются вопросы, которых или не существует или они по-другому работают в go. Рассмотрена передача параметров по ссылке и значению, но в go есть только передача по значению; предупреждается о переполнении стэка — ну это возможно, если всю память переполнить, впринципе…
Кстати, несколько раз слышал такое слово в слово от программистов. Один раз и про свой код довелось — до сих пор в раздумьях, как инженер может обосновывать свое суждение «я так вижу»…
Станет получше, более конкурентный GC и не всегда съедающий по целому кванту времени, да. Но если есть GC и активно растущая куса, то рано или поздно отложенную на предыдущих шагах GC работу придется сделать и отложенная длительная пауза GC станет только в разы больше.
Фактически сейчас улучшается самый ожидаемый случай с GC, и ухудшается самый печальный.
Не совсем с GC. Если было бы так, то при любом размере кучи не было бы длительных остановок.
Верным утверждением было бы, что 90-й процентиль stop-the-world не превосходит миллисекунды. В подтверждение моих слов,например — это на 1.6, где вроде как все паузы должны были быть менее 10ms, но на большой map паузы достигают намного больших значений.
Про «фигак-фигак» — не вижу взаимосвязи между «серьезные ребята» и «хороший код».
тоже странный аргумент: если ребята дошли до той черты, когда дополнительный вызов метода значим, то зачем они взяли язык с GC? Ну или, почему тогда на этот «супер-критичный» по производительности метод не бенчмарков?
В общем, не думаю, что такова история. Больше похоже на фигак-фигак.
Непонятна необходимость делать громадный метод со сложной логикой, которую после побеждаем при помощи goto. Хотя можно было сразу делать простые методы. Сейчас же он делаем Много чего в себе, ответственность у него большая, как следствие тесты не маленькие, а такие же большие по сути.
Если говорить именно о том, что с fasthttp будет сильно круче, то не уверен, несколько быстрее будет. Fasthttp выделяет намного меньше памяти и соответственно GC меньше съест. Правда код на нем, по личному опыту, трудно поддерживать: неинформативные ошибки, попытка почитать код приводит к чтению функций по 200-400 строк…
Бенчмарки можно посмотреть тут
Как верно сказали ниже, map содержит указатель, но и он передается по значению.
То же самое справедливо и в отношении каналов. Только с учетом того, что его вместимость мы определяем сразу и не можем поменять, не создавая новый канал.
Map — это структура, передается по значению. Собственно поэтому возможны вот такие вещи.
В целом для большого проекта получился быстрый переход. Но конечно не человекодни.
На все около 7 минут ушло.
А по теме статьи — да, проблема есть, но я не понимаю, зачем давать такие задания после ознакомления с кодом кандидата. А это бывает, к сожалению, часто. Как и тестовые задания на несколько дней…
Если считать, что в go есть передача по ссылке и типы slice, map и chan ссылочные, то такую ошибку сделать легко.
Мне кажется, что желание дженериков везде и всегда, сродни преждевременной оптимизации или неоправданному расширению задачи: надо было сделать для одного типа, но программист пробует написать обобщенный код.
Дженерики нужны, конечно, кодогенерация не помогает всегда, да и код усложняет в разы, как и отладку сгенерированного кода. И в самой стандартной библиотеке она не используется, то есть это решение и разработчикам golang не сильно нравится.
Но да, дженерики не настолько важны в действительной жизни. Рабочий код пишется и без них.
Можно сделать указатель, но в функцию его передашь все равно по значению. С unsafe то же самое. Ну будет uintptr — это не ссылка, а вполне себе значение.
Но для пробы посмотрел вторую лекцию и был удивлен: в лекции рассматриваются вопросы, которых или не существует или они по-другому работают в go. Рассмотрена передача параметров по ссылке и значению, но в go есть только передача по значению; предупреждается о переполнении стэка — ну это возможно, если всю память переполнить, впринципе…
Самый отвязный доклад с модной и продуманной архитектурой!
Фактически сейчас улучшается самый ожидаемый случай с GC, и ухудшается самый печальный.
Верным утверждением было бы, что 90-й процентиль stop-the-world не превосходит миллисекунды. В подтверждение моих слов,например — это на 1.6, где вроде как все паузы должны были быть менее 10ms, но на большой map паузы достигают намного больших значений.
Про «фигак-фигак» — не вижу взаимосвязи между «серьезные ребята» и «хороший код».
В общем, не думаю, что такова история. Больше похоже на фигак-фигак.