web-dev-qa-db-ja.com

Goのio.Writer-それらを理解しようとしている初心者

Goの初心者として、私はio.Writerを理解するのに問題があります。

私の目標:構造体を取り、それをjsonファイルに書き込みます。

アプローチ:
-encoding/json.Marshalを使用して構造体をバイトに変換します
-それらのバイトをos.Fileライターにフィードします

これが私がそれを機能させた方法です:

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)
}

この記事 を読んだ後、プログラムを次のように変更しました。

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)
}

私の意見では、最初の例は初心者にとってより簡単で理解しやすいです...しかし、2番目の例は目標を達成するためのGoの慣用的な方法であると感じています。

質問:
1。上記の仮定は正しいですか(2番目のオプションは慣用的になります)?
2。上記のオプションに違いはありますか?どちらのオプションが良いですか?
3。同じ目標を達成する他の方法は?

ありがとうございました、

WM

11
whyme

2番目の方法を使用する利点は、Writerインターフェイスを渡す場合、Writeを実装するanythingを渡すことができることです。構造体メソッドを変更せずに、ファイルだけでなく、たとえばhttp.ResponseWriter、またはstdout os.Stdout

この便利なブログ投稿はパッケージで見ることができます ioウォークスルー 。作成者は、パラメーターのリーダーおよびライターとして渡すと、コードがより柔軟になると主張しています。これは、非常に多くの関数がReaderおよびWriterインターフェイスを使用しているためです。

Go moreを使用するようになると、標準ライブラリがReaderおよびWriterインターフェイスにどれだけ依存しているかに気付くでしょう。おそらく、それを高く評価するようになります:)

したがって、この関数(名前が変更されました):

// 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
}

File、httpResponse、ユーザーStdout、または単純なバイトバッファ;テストが少し簡単になります。

何をしているのかという理由で名前を変更しました。つまり、この関数はPerson構造体を取ります。

  1. 構造体をjson表現にマーシャリングします
  2. JsonをWriterに書き込みます
  3. マーシャリング/書き込みに起因するエラーを返します

もう1つ、Writerデータ型ではないため(== --- ==)とは何かについて混乱する可能性がありますではなく、interface-これはデータ型の動作であり、型が実装する事前定義されたメソッドです。したがって、Write()メソッドを実装するものはすべて、ライターと見なされます。

これは初心者にとって最初は理解するのが少し難しいかもしれませんが、インターフェースを理解するのに役立つオンラインのリソースがたくさんあります(そして、ReadWritersは、Error()とともに遭遇するより一般的なインターフェースのいくつかです(ei。すべてのエラー))。

9
Nevermore