2015-06-23 3 views
-1

У меня есть приложение 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()) 
} 
+1

Пожалуйста показать некоторые из кода в соскоба статье. Я предполагаю, что он также читает или пишет? Трудно сказать вам, как использовать каналы, потому что вы далеки от решения, которое их использует. Как и в этот момент, я мог бы написать ваш код бесконечным набором способов достижения ваших целей, большинство из них, вероятно, не будут включать каналы. Увеличение параллелизма просто вызовет больше проблем с блокировкой ... Каналы - это просто инструмент для общения между goroutines (параллелизм). Я думаю, вам нужно сериализовать процесс, а не сделать его более параллельным. – evanmcdonnal

+0

Thanks; Я включил функцию царапины в открытии сообщения. Каков наилучший способ заставить функцию scrape работать только один раз за раз? –

+0

Лучший способ обеспечить «взаимное исключение» вокруг одного ресурса - использовать [mutex] (http://golang.org/pkg/sync/#Mutex) – JimB

ответ

Смежные вопросы