Ответы пользователя по тегу Go
  • Почему в Go зависает http.Get()?

    Я бы повесил timeout (уменьшил бы его до приемлемого).
    Если ответ не пришёл в течение N секунд - возвращать ошибку.
    Timeout создается при помощи добавления кастомного http.Transport в конструктор http.Client (15-20 строки).

    Код программы c timeout'ом.
    package main
    
    import (
    	"bytes"
    	"errors"
    	"fmt"
    	"io/ioutil"
    	"net"
    	"net/http"
    	"time"
    )
    
    func getPage(url string, timeout time.Duration) (HTML string, e error) {
    	client := &http.Client{
    		Transport: &http.Transport{
    			Dial: func(network, addr string) (net.Conn, error) {
    				return net.DialTimeout(network, addr, timeout)
    			},
    			ResponseHeaderTimeout: timeout,
    		},
    	}
    
    	req, e := http.NewRequest("GET", url, nil)
    	if e != nil {
    		return "", errors.New(fmt.Sprintf(`http.NewRequest failed: %s`, e.Error()))
    	}
    
    	resp, e := client.Do(req)
    	if e != nil {
    		return "", errors.New(fmt.Sprintf("client.Do failed: %s)", e.Error()))
    	}
    	defer resp.Body.Close()
    
    	bodyAsBytes, e := ioutil.ReadAll(resp.Body)
    	if e != nil {
    		return "", errors.New(fmt.Sprintf("ioutil.ReadAll failed: %s)", e.Error()))
    	}
    	bodyAsBuffer := bytes.NewBuffer(bodyAsBytes)
    
    	return bodyAsBuffer.String(), nil
    }
    
    func main() {
    	HTML, e := getPage("http://google.com/", time.Duration(1*time.Second))
    	if e != nil {
    		fmt.Printf("[ERROR] %s\n", e.Error())
    	} else {
    		fmt.Printf("[INFO] %s\n", HTML)
    	}
    }



    Если timeout выставить так (1 наносекунда), то программа выведет сообщение об ошибке:
    >>> HTML, e := getPage("http://google.com/", time.Duration(1*time.Nanosecond))
    [ERROR] client.Do failed: Get http://google.com/: i/o timeout)


    Если timeout выставить так (5 секунд), то программа выведет HTML странички:
    HTML, e := getPage("http://google.com/", time.Duration(5*time.Second))
    [INFO] <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage"><head><meta content="........


    Я сделал бы pool задач на скачивание. Если некоторые не завершились успехом - перезапускал бы их через некоторое время. На мой взгляд это типичная задача pool - worker:
    1) Можно решать через resque + goworker например. Это дает наглядность. Упавшие задачи можно сразу перезапустить, увидеть что пошло не так. Статистика копится;
    2) Можно решать, создав горутину как pool и N горутин как worker'ы. И самому создать логику обработки упавших задач.
    Ответ написан
    Комментировать
  • Веб-фреймворк для Го?

    1. revel (похоже на rails);
    2. beego (похоже на rails). На нём например gowalker написан;
    3. martini (похоже на sinatra);
    Я бы на эти фреймворки посмотрел, потрогал, повдохновялся, но использовал бы отдельные библиотеки. Благо их в go много (mux, websocket, log, BDD test, test assert, resque worker'ы ...);
    Ответ написан
    1 комментарий