【问题标题】:io.Writer in Go - beginner trying to understand themGo 中的 io.Writer - 试图理解它们的初学者
【发布时间】:2017-10-03 05:51:16
【问题描述】:

作为 Go 的初学者,我无法理解 io.Writer

我的目标:获取一个结构并将其写入一个 json 文件。

方法:
- 使用 encoding/json.Marshal 将我的结构转换为字节
- 将这些字节提供给os.File Writer

这就是我的工作方式:

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

看了this article之后,我把我的程序改成了这样:

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

在我看来,第一个例子对于初学者来说更直接和更容易理解......但我觉得第二个例子是实现目标的 Go 惯用方式。

问题:
1. 上述假设是否正确(第二个选项是 Go 惯用的)?
2.以上选项有区别吗?哪个选项更好?
3. 实现相同目标的其他方法?

谢谢,

WM

【问题讨论】:

    标签: go writer


    【解决方案1】:

    使用第二种方法的好处是,如果你传递一个Writer 接口,你可以传递实现Writeanything——这不仅是一个文件,而且是一个@987654324 @,例如,或 stdout os.Stdout,而不更改结构方法。

    您可以在 io walkthrough 包上看到这篇方便的博客文章。作者认为,作为参数读取器和写入器传递会使您的代码更加灵活,部分原因是有很多函数使用ReaderWriter 接口。

    随着您越来越多地使用 Go,您会注意到标准库对 ReaderWriter 接口的依赖程度,并且可能会开始欣赏它 :)

    所以这个函数(重命名):

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

    会写入文件、http 响应、用户的标准输出,甚至是简单的字节缓冲区 ;让测试变得更简单。

    我重命名它是因为它的作用;也就是说,这个函数需要一个Person 结构并且:

    1. 将结构编组为 json 表示形式
    2. 将 json 写入 Writer
    3. 返回由编组/写入引起的任何错误

    还有一点,您可能对Writer 是什么感到困惑,因为它不是数据类型,而是接口 > -- 这是一种数据类型的行为,一种类型实现的预定义方法。那么,任何实现Write() 方法的东西都被认为是作家。

    这对于初学者来说可能有点难以掌握,但是网上有很多资源可以帮助理解接口(@98​​7654334@ 是一些更常见的接口,还有Error()(ei.所有错误))。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-30
      • 1970-01-01
      • 2020-12-11
      • 2016-01-05
      • 2017-06-27
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多