2017-05-04 20 views
6

Jako początkujący użytkownik Go, mam problemy ze zrozumieniem io.Writer.io.Writer in Go - początkujący próbuje je zrozumieć

Mój cel: weź strukturę i zapisz ją w pliku json.

Podejście:
- użyj encoding/json.Marshal przekonwertować struct w bajtach
- nakarmić te bajty do os.File Writer

To jak mam to działa:

package main 

import (
    "os" 
    "encoding/json" 
) 

type Person struct { 
    Name string 
    Age uint 
    Occupation []string 
} 

func MakeBytes(p Person) []byte { 
    b, _ := json.Marshal(p) 
    return b 
} 

func main() { 
    gandalf := Person{ 
     "Gandalf", 
     56, 
     []string{"sourcerer", "foo fighter"}, 
    } 

    myFile, err := os.Create("output1.json") 
    if err != nil { 
     panic(err) 
    } 
    myBytes := MakeBytes(gandalf) 
    myFile.Write(myBytes) 
} 

Po przeczytaniu this article, Zmieniłem program na:

package main 

import (
    "io" 
    "os" 
    "encoding/json" 
) 

type Person struct { 
    Name string 
    Age uint 
    Occupation []string 
} 

// Correct name for this function would be simply Write 
// but I use WriteToFile for my understanding 
func (p *Person) WriteToFile(w io.Writer) { 
    b, _ := json.Marshal(*p) 
    w.Write(b) 
} 

func main() { 
    gandalf := Person{ 
     "Gandalf", 
     56, 
     []string{"sourcerer", "foo fighter"}, 
    } 

    myFile, err := os.Create("output2.json") 
    if err != nil { 
     panic(err) 
    } 
    gandalf.WriteToFile(myFile) 
} 

Moim zdaniem, pierwszy przykład jest prostszy i łatwiejszy do zrozumienia dla początkującego ... ale mam wrażenie, że drugim przykładem jest idiomatyczny sposób osiągnięcia celu.

Pytania:
1. Czy powyższe założenie jest poprawne (ta druga opcja to Idiomatyczna)?
2. Czy jest różnica w powyższych opcjach? Która opcja jest lepsza?
3. inne sposoby osiągnięcia tego samego celu?

Dziękuję

WM

Odpowiedz

6

Korzyści wynikające z zastosowania drugiej metody jest to, że jeśli jesteś przejazdem interfejs Writer, można przekazać nic który implementuje Write - to nie jest tylko plik ale na przykład http.ResponseWriter lub stdout os.Stdout, bez zmiany metod struktury.

Możesz zobaczyć ten poręczny blog na opakowaniu io walkthrough. Autor twierdzi, że przekazywanie jako czytników parametrów i programów piszących zwiększa elastyczność kodu, częściowo dlatego, że wiele funkcji korzysta z interfejsu Reader i Writer.

Jak dojdziesz do korzystania Go więcej, zauważysz, ile średnia biblioteka oprze na Reader i Writer interfejsów i prawdopodobnie przyjść do jej :)

więc ta funkcja (nazwa zmieniona) doceniają:

// writes json representation of Person to Writer 
func (p *Person) WriteJson(w io.Writer) error { 
    b, err := json.Marshal(*p) 
    if err != nil { 
     return err 
    } 
    _, err = w.Write(b) 
    if err != nil { 
     return err 
    } 
    return err 
} 

napisze do Plik http Response, użytkownik za Stdout, lub nawet prosty bajt bufora; dzięki czemu testowanie jest nieco prostsze.

Zmieniono nazwę tego z powodu tego, co jest; czyli funkcja ta zajmuje Person struct oraz:

  1. Marszałków strukturę, w json reprezentacji
  2. Zapisuje json do Writer
  3. Returns ewentualne błędy wynikające z zestawiania/pisanie

Jeszcze jedno, możesz być zdezorientowany, jeśli chodzi o Co to jest Writer, ponieważ jest to typ danych , a nie typ danych, ale raczej interfejs - jest to zachowanie typu danych, predefiniowana metoda implementowana przez typ. Wszystko, co implementuje metodę Write(), jest uważane za pisarz.

Początkowo może to być nieco trudne dla początkujących, ale istnieje wiele zasobów online, które pomagają zrozumieć interfejsy (i ReadWriters to niektóre z bardziej popularnych interfejsów do spotkania, wraz z Error() (wszystkie błędy)).