Pull to refresh

Comments 30

Одна из лучших статей по Go которые я видел за последний год.
Выбрана подходящая задача и стиль повествования близок к идеалу.
К комментарию dmitriko и добавить, к сожалению, нечего.

PS: Посты с тегом Go зачастили в последнее время, и это здорово!
Показательный пример, да.

Правда хранить хеши в файле — сомнительное удовольствие. (Разве что в качестве примера). Проще ведь заново их пересчитывать каждый раз.

И стоит-таки соблюдать naming conventions.
4 замечания пока что:

1. Зачем вы запустили несколько потоков, но в каждом из них делаете sleep? Какой смысл то?
2. На мой взгляд хранение хешей посещённых страниц в глобальной переменной абсолютно неоправданно.
3. Есть ли реальный смысл делать defer в функции main? Ведь файлы в любом случае позакрываются при выходе из программы.
4. Для хранения хешей используется HashMap. А нет ли для go структуры данных Set?
1. Видимо, чтобы не спамить сервер запросами.
2. +1
3. То же самое, что не делать close() в Java. ИМХО ресурсы всегда надо за собой подчищать, это вообще должно войти в привычку.
4. Нет, нету. А зачем, если Set по, сути, есть Map в {1, 0}?
Если я правильно понимаю, что «потоки» в go это как greenlet в Python, то sleep нужен как раз для переключения «потоков». Кооперативная многозадачность. Только один «поток» может работать в одно время.
Да не, тоже безсмысленно. Хоть в go и кооперативная многозадачность, но поток yield-ится при сетевых операциях (скачивание веб-странички). Этого должно быть более чем достаточно.
Да, это правильно. В более-менее свежих версиях языка шедулер переключает горутины при системных вызовах. От for { } не спасает, а вот for { fmt.Println("...") } уже не будет отбирать основной поток.
1. Чтобы не спамить сервер запросами можно запустить всё в один поток и не возиться с каналами / горутинами и пр.
4. Применительно к задаче из топика, используя Set вместо Map можно немного сэкономить память. А в общем, для Set обычно реализуют некоторые полезные функции типа пересечений / объединений, вычитаний и т.п. (хотя для данной задачи они и не требуются).
1. Да, наверное. Я так полагаю, что это для демонстрации возможности.
4. Ну это от реализации зависит. Даже в Java Set это просто Map, у которого используются только ключи.
flag.Parse() не рекомендуют делать внутри init().
В основном из-за того, что ваш пакет могут использовать другие люди. И вызов глобального flag.Parse() внутри вашего пакета может оказаться шоком для них. Флаги с конфликтующими именами могут быть проигнорированы, и не будет никакого сообщения об ошибке.
Кроме того, утилита go test синтезирует собственную func main(), где вызывает flag.Parse().
Спасибо, указал что так делать нехорошо!
Стоит заметить, что при этом вполне правильно задавать флаги прямо в var модуля (что в вашем случае будет правильнее) или в ините — они корректно достаются и отображаются при -h. Собственно, это go-way для используемых модулями флагов, и на мой взгляд волшебная фича!
Статья просто великолепна, спасибо большое! Очень здорово и очень классным языком рассказано про то, как удобно и быстро на Go делать достаточно сложные приложения.
Dreadd, спасибо. Замечательный материал.

Кстати вопрос к знающим по поводу размеров исполняющего файла. Можно ли как-нибудь все это дело разбить? Т.е. сторонние либы отдельно, сам экзешник отдельно?
Кстати вопрос к знающим по поводу размеров исполняющего файла. Можно ли как-нибудь все это дело разбить? Т.е. сторонние либы отдельно, сам экзешник отдельно?

А зачем? Весь рантайм статически компилируется в один бинарник. В современных системах — это очень удобно, т.к. нету никаких зависимостей, что сказачно облегчает деплоймент.
В принципе, вы правы. Может быть я фантазирую, но если приложение цепляет очень много зависимостей и часто изменяется, не проще ли было бы зависимости развернуть только единожды, а изменяемую часть постоянно менять с версиями?
Так а в чём выигрыш? Библиотеки-зависимости тоже меняются. В итоге времени всё равно больше уйдёт.

Вот из опыта 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.
Выигрыш может быть в том, что если у вас множество проектов, которые работают с одним окружением библиотек, то не нужно все это окружение таскать в каждом отдельном проекте, а так же при обновлении окружения не нужно перекомпилировать все зависимые проекты… В общем, когда есть возможность выбора, это всегда лучше, чем отсутствие выбора… :)
Когда слишком много выбора, у некоторых руки чешутся использовать вещи не по назначению. Go полон компромиссов. Создатели постарались добиться максимальной простоты, во всём. Где-то это ограничивает программистов, но как правило оно того стоит.

Сейчас область применения Go — это утилитки и веб-серверы. Нету необходимости использовать общее окружение.
Если нужно больше цитат, в том числе уже удаленные из модерации, приходи в личку, поговорим :)
+1, так все и есть. Ваш комент помог. Спасибо.
Не писался ни одни из файлов, пока метку доступа с os.O_CREATE не поменял на os.O_RDWR
Спасибо, ваш комент помог осваивавать этот язык =)
Как-то в 2018, видимо, тема с Go померла. Больше нет теплых ламповых статей.
Неужели все переболели?
Спасибо за статью.
Есть только пару вопросов.
1. Почему по коду не придерживается стилистика camelCase?
2. goquery.ParseUrl — Может ли получать данных с https протокола игнорирую ошибки валидации сертификатов ssl?
нашел я ответ на 2-й вопрос

Данная настройка отключает проверку 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 
		}
	}
Sign up to leave a comment.

Articles