У меня есть приложение Golang, которое хранит URL-адреса (предоставленные в качестве параметра запроса) в базе данных. Хранение URL'ами, производится с помощью следующего метода:Использование канала в режиме go
func AddArticle(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
queryParam := r.FormValue("url")
insertedId := dao.SaveArticle(db, queryParam)
glog.Infof("add hostname %s, id: %d", getHostnameFromUrl(queryParam), insertedId)
// start routine which scrapes url
go dao.ScrapeArticle(db, insertedId)
// finally output confirmation page
renderObject := map[string]string{"hostname": getHostnameFromUrl(queryParam)}
render.DisplayPage(w, r, renderObject, "confirmation.html")
}
}
Теперь это работает отлично, но по какой-то причине, когда много новых адресов сохраняются, то SQLite база данных говорит мне, что тупиковая ситуация произошла. Поэтому я думал, что хочу использовать каналы, чтобы предотвратить эти мертвые блокировки. Но, к сожалению, я не уверен, как начать с этого.
В общем, что я хочу это:
- для каждого добавленного URL, запустите функцию dao.ScrapeArticle (передвигайте insertedID в качестве ссылки статьи сразу показать страницу подтверждения (ака
url added
) - Когда. соскоб из artcle сделан, функция добавляет Царапины информации в базу данных SQLite (путем обновления на ID)
Я не знаю, как начать и нуждаются в помощи. Fe, где я определить канал?
Моя функция скребок выглядит следующим образом:
func ScrapeArticle(db *sql.DB, id int64) {
// time function duration
start := time.Now()
// storedArticle contains information stored in db which need to be updated through scraping
storedArticle := getArticleById(db, id)
// init goquery
doc, err := goquery.NewDocument(storedArticle.Url.String)
glog.Info("scraping article with url --> ", storedArticle.Url.String)
if err != nil {
glog.Error("error while scraping article with id %d -- > ", storedArticle.ID, err)
return
}
// start scraping page title
doc.Find("head").Each(func(i int, s *goquery.Selection) {
pageTitle := s.Find("title").Text()
storedArticle.Name = sql.NullString{String: strings.TrimSpace(pageTitle), Valid: true}
})
// now get meta description field
doc.Find("meta").Each(func(i int, s *goquery.Selection) {
if name, _ := s.Attr("name"); strings.EqualFold(name, "description") {
description, _ := s.Attr("content")
storedArticle.Description = sql.NullString{String: strings.TrimSpace(description), Valid: true}
}
})
// if unable to scrape title, then use url
if len(storedArticle.Name.String) == 0 {
storedArticle.Name.String = storedArticle.Url.String
}
// if unable to scrape description, then use default text
if len(storedArticle.Description.String) == 0 {
storedArticle.Description.String = noDescription
}
// debugging info
glog.Infof("scraped title --> %s (length: %d)", storedArticle.Name.String, len(storedArticle.Name.String))
glog.Infof("scraped description --> %s (length: %d)", storedArticle.Description.String, len(storedArticle.Description.String))
// after succesfull scraping, add page title (and more?) to article in db
updateArticle(db, storedArticle)
elapsed := time.Since(start)
glog.Infof("scraping article %d completed in %s", storedArticle.ID.Int64, elapsed.String())
}
Пожалуйста показать некоторые из кода в соскоба статье. Я предполагаю, что он также читает или пишет? Трудно сказать вам, как использовать каналы, потому что вы далеки от решения, которое их использует. Как и в этот момент, я мог бы написать ваш код бесконечным набором способов достижения ваших целей, большинство из них, вероятно, не будут включать каналы. Увеличение параллелизма просто вызовет больше проблем с блокировкой ... Каналы - это просто инструмент для общения между goroutines (параллелизм). Я думаю, вам нужно сериализовать процесс, а не сделать его более параллельным. – evanmcdonnal
Thanks; Я включил функцию царапины в открытии сообщения. Каков наилучший способ заставить функцию scrape работать только один раз за раз? –
Лучший способ обеспечить «взаимное исключение» вокруг одного ресурса - использовать [mutex] (http://golang.org/pkg/sync/#Mutex) – JimB