Комментарии 30
Одна из лучших статей по Go которые я видел за последний год.
Выбрана подходящая задача и стиль повествования близок к идеалу.
Выбрана подходящая задача и стиль повествования близок к идеалу.
+11
К комментарию dmitriko и добавить, к сожалению, нечего.
PS: Посты с тегом Go зачастили в последнее время, и это здорово!
PS: Посты с тегом Go зачастили в последнее время, и это здорово!
+4
Показательный пример, да.
Правда хранить хеши в файле — сомнительное удовольствие. (Разве что в качестве примера). Проще ведь заново их пересчитывать каждый раз.
И стоит-таки соблюдать naming conventions.
Правда хранить хеши в файле — сомнительное удовольствие. (Разве что в качестве примера). Проще ведь заново их пересчитывать каждый раз.
И стоит-таки соблюдать naming conventions.
+1
4 замечания пока что:
1. Зачем вы запустили несколько потоков, но в каждом из них делаете sleep? Какой смысл то?
2. На мой взгляд хранение хешей посещённых страниц в глобальной переменной абсолютно неоправданно.
3. Есть ли реальный смысл делать defer в функции main? Ведь файлы в любом случае позакрываются при выходе из программы.
4. Для хранения хешей используется HashMap. А нет ли для go структуры данных Set?
1. Зачем вы запустили несколько потоков, но в каждом из них делаете sleep? Какой смысл то?
2. На мой взгляд хранение хешей посещённых страниц в глобальной переменной абсолютно неоправданно.
3. Есть ли реальный смысл делать defer в функции main? Ведь файлы в любом случае позакрываются при выходе из программы.
4. Для хранения хешей используется HashMap. А нет ли для go структуры данных Set?
0
1. Видимо, чтобы не спамить сервер запросами.
2. +1
3. То же самое, что не делать close() в Java. ИМХО ресурсы всегда надо за собой подчищать, это вообще должно войти в привычку.
4. Нет, нету. А зачем, если Set по, сути, есть Map в {1, 0}?
2. +1
3. То же самое, что не делать close() в Java. ИМХО ресурсы всегда надо за собой подчищать, это вообще должно войти в привычку.
4. Нет, нету. А зачем, если Set по, сути, есть Map в {1, 0}?
0
Если я правильно понимаю, что «потоки» в go это как greenlet в Python, то sleep нужен как раз для переключения «потоков». Кооперативная многозадачность. Только один «поток» может работать в одно время.
0
Да не, тоже безсмысленно. Хоть в go и кооперативная многозадачность, но поток yield-ится при сетевых операциях (скачивание веб-странички). Этого должно быть более чем достаточно.
-1
Я как раз писал статью на хабре, в которой описано, как работают горутины. В том числе и как их переключает планировщик.
0
1. Чтобы не спамить сервер запросами можно запустить всё в один поток и не возиться с каналами / горутинами и пр.
4. Применительно к задаче из топика, используя Set вместо Map можно немного сэкономить память. А в общем, для Set обычно реализуют некоторые полезные функции типа пересечений / объединений, вычитаний и т.п. (хотя для данной задачи они и не требуются).
4. Применительно к задаче из топика, используя Set вместо Map можно немного сэкономить память. А в общем, для Set обычно реализуют некоторые полезные функции типа пересечений / объединений, вычитаний и т.п. (хотя для данной задачи они и не требуются).
+1
flag.Parse() не рекомендуют делать внутри init().
В основном из-за того, что ваш пакет могут использовать другие люди. И вызов глобального flag.Parse() внутри вашего пакета может оказаться шоком для них. Флаги с конфликтующими именами могут быть проигнорированы, и не будет никакого сообщения об ошибке.
Кроме того, утилита go test синтезирует собственную func main(), где вызывает flag.Parse().
В основном из-за того, что ваш пакет могут использовать другие люди. И вызов глобального flag.Parse() внутри вашего пакета может оказаться шоком для них. Флаги с конфликтующими именами могут быть проигнорированы, и не будет никакого сообщения об ошибке.
Кроме того, утилита go test синтезирует собственную func main(), где вызывает flag.Parse().
+3
Спасибо, указал что так делать нехорошо!
0
Статья просто великолепна, спасибо большое! Очень здорово и очень классным языком рассказано про то, как удобно и быстро на Go делать достаточно сложные приложения.
+1
Кстати вопрос к знающим по поводу размеров исполняющего файла. Можно ли как-нибудь все это дело разбить? Т.е. сторонние либы отдельно, сам экзешник отдельно?
А зачем? Весь рантайм статически компилируется в один бинарник. В современных системах — это очень удобно, т.к. нету никаких зависимостей, что сказачно облегчает деплоймент.
0
В принципе, вы правы. Может быть я фантазирую, но если приложение цепляет очень много зависимостей и часто изменяется, не проще ли было бы зависимости развернуть только единожды, а изменяемую часть постоянно менять с версиями?
0
Так а в чём выигрыш? Библиотеки-зависимости тоже меняются. В итоге времени всё равно больше уйдёт.
Вот из опыта Iron.io:
Вот из опыта Iron.io:
Go compiles into a single, static binary file so deployment is simply putting the file on a server and starting it up. No dependencies required. No runtime required (you don't need to install Go on the server). And it's small; the IronMQ binary is ~6MB.
If something goes wrong after deploying and you need to roll back, you can just stop the bad process then start the previous binary. You don't need to worry about a dependency being upgraded since the entire program is compiled into a single binary.
+1
Выигрыш может быть в том, что если у вас множество проектов, которые работают с одним окружением библиотек, то не нужно все это окружение таскать в каждом отдельном проекте, а так же при обновлении окружения не нужно перекомпилировать все зависимые проекты… В общем, когда есть возможность выбора, это всегда лучше, чем отсутствие выбора… :)
0
Когда слишком много выбора, у некоторых руки чешутся использовать вещи не по назначению. Go полон компромиссов. Создатели постарались добиться максимальной простоты, во всём. Где-то это ограничивает программистов, но как правило оно того стоит.
Сейчас область применения Go — это утилитки и веб-серверы. Нету необходимости использовать общее окружение.
Сейчас область применения Go — это утилитки и веб-серверы. Нету необходимости использовать общее окружение.
0
Если нужно больше цитат, в том числе уже удаленные из модерации, приходи в личку, поговорим :)
+1
Не писался ни одни из файлов, пока метку доступа с os.O_CREATE не поменял на os.O_RDWR
0
Ещё одно спасибо, спустя 2 года.
0
Спасибо! =)
0
Как-то в 2018, видимо, тема с Go померла. Больше нет теплых ламповых статей.
Неужели все переболели?
Неужели все переболели?
0
Спасибо за статью.
Есть только пару вопросов.
1. Почему по коду не придерживается стилистика camelCase?
2. goquery.ParseUrl — Может ли получать данных с https протокола игнорирую ошибки валидации сертификатов ssl?
Есть только пару вопросов.
1. Почему по коду не придерживается стилистика camelCase?
2. goquery.ParseUrl — Может ли получать данных с https протокола игнорирую ошибки валидации сертификатов ssl?
0
нашел я ответ на 2-й вопрос
Данная настройка отключает проверку SSL сертификатов на валидность:
Данная настройка отключает проверку SSL сертификатов на валидность:
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
x, err := goquery.ParseUrl("https://site.com")
if err == nil {
if s := strings.TrimSpace(x.Find(".panel-heading").Text()); s != "" {
c <- s
}
}
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Знакомство с Go — пишем граббер веб страниц с многопоточностью и блудницами