作为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 idiomatic)?
2.上述选项有区别吗?哪个选项更好?
3.实现同一目标的其他方式?
谢谢,
WM
答案 0 :(得分:6)
使用第二种方法的好处是,如果您传递的是Writer
接口,则可以传递实现Write
的任何 - 这不仅仅是一个文件但是http.ResponseWriter
,例如,或stdout os.Stdout
,而不更改结构方法。
您可以在包io walkthrough上看到这篇方便的博文。作者认为,作为参数读者和作者传递会使您的代码更加灵活,部分原因是因为许多函数使用Reader
和Writer
接口。
当您开始使用Go更多时,您会注意到标准库在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
}
会写入文件,http 响应,用户的标准输出,甚至是简单的字节缓冲区强>;使测试更简单。
我因为做了什么而重新命名;也就是说,此函数采用Person
结构和:
Writer
还有一件事,你可能会对 Writer 的含义感到困惑,因为不是数据类型,而是接口 - 这是数据类型的行为,类型实现的预定义方法。那么,任何实现Write()
方法的东西都被认为是作家。
这对初学者来说可能有点困难,但是在线有很多资源可以帮助理解界面(ReadWriters
是一些比较常见的界面,以及{{1} (ei。所有错误))。