2013-05-01 15 views
23

Jak przekonwertować poniższy kod, aby użyć strumieni/potoków, aby nie trzeba było czytać całej zawartości w pamięci? Coś jak: http.Get("http://example.com/").Pipe("./data.txt")Jak potokować odpowiedź HTTP do pliku w folderze Go?

package main 
import ("net/http";"io/ioutil") 

func main() { 
     resp, err := http.Get("http://example.com/") 
     check(err) 
     defer resp.Body.Close() 
     body, err := ioutil.ReadAll(resp.Body) 
     check(err) 
     err = ioutil.WriteFile("./data.txt", body, 0666) 
     check(err) 
} 
func check(e error) { 
     if e != nil { 
       panic(e) 
     } 
} 
+1

Odpowiedź Get zawiera pole Body hat implementujące Reader. Możesz po prostu przekazać to do jakiejś funkcji, która zapisuje jej zawartość do twojego pliku. W żadnym momencie cała zawartość ciała nie jest ładowana do pamięci, chyba że o to poprosisz. – fuz

Odpowiedz

38

Jak o io.Copy()? Jego dokumentację można znaleźć pod adresem: http://golang.org/pkg/io/#Copy

Jest to jednak bardzo proste. Daj mu io.Reader i io.Writer i kopiuje dane po jednej małej porcji na raz (np. Nie wszystkie w pamięci naraz).

Więc możesz spróbować napisać coś takiego:

func main() { 
    resp, err := http.Get("...") 
    check(err) 
    defer resp.Body.Close() 
    out, err := os.Create("filename.ext") 
    if err != nil { 
    // panic? 
    } 
    defer out.Close() 
    io.Copy(out, resp.Body) 
} 

Nie testowałem powyżej; Po prostu zhakowałem to szybko z powyższego przykładu, ale powinno być blisko, jeśli nie na pieniądze.

+0

Wielkie dzięki. Działa dobrze! – ekanna

+3

Należy zauważyć, że ten kod nie sprawdza zwracanych błędów jednej z instrukcji 'Close()'. –

+3

@Nie, to dość powszechne (nawet idiomatyczne), aby odroczyć zamknięcie i zignorować błąd. Zwykle niewiele można zrobić z powodu bliskiego błędu, z wyjątkiem krzyczenia w systemie operacyjnym. – mna