io.Writer 在 Go 中 - 初学者试图理解它们
io.Writer in Go - beginner trying to understand them
作为围棋的初学者,我在理解上遇到了问题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
使用第二种方法的好处是,如果你要传递一个 Writer
接口,你可以传递 任何实现 Write
的东西 -- 那不仅是文件,而且是 http.ResponseWriter
,例如,或 stdout os.Stdout
,无需更改结构方法。
您可以在包裹 io walkthrough 上看到这个方便的博客 post。作者认为作为参数读取器和写入器传递会使您的代码更加灵活,部分原因是很多函数使用 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
}
会写入 File、http Response、用户的 Stdout,甚至一个简单的 byte Buffer;使测试更简单。
我重命名它是因为它的作用;也就是说,此函数采用 Person
结构和:
- 将结构编组为 json 表示
- 将 json 写入
Writer
- Returns 由 marshalling/writing
引起的任何错误
还有一件事,您可能对 Writer 是什么感到困惑,因为它不是数据类型,而是接口——这是一种数据类型的行为,一种类型实现的预定义方法。然后,任何实现 Write()
方法的东西都被认为是一个 writer。
初学者一开始可能有点难以掌握,但是网上有很多资源可以帮助理解界面(ReadWriters
是一些比较常见的界面,还有 Error()
(即所有错误))。
作为围棋的初学者,我在理解上遇到了问题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
使用第二种方法的好处是,如果你要传递一个 Writer
接口,你可以传递 任何实现 Write
的东西 -- 那不仅是文件,而且是 http.ResponseWriter
,例如,或 stdout os.Stdout
,无需更改结构方法。
您可以在包裹 io walkthrough 上看到这个方便的博客 post。作者认为作为参数读取器和写入器传递会使您的代码更加灵活,部分原因是很多函数使用 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
}
会写入 File、http Response、用户的 Stdout,甚至一个简单的 byte Buffer;使测试更简单。
我重命名它是因为它的作用;也就是说,此函数采用 Person
结构和:
- 将结构编组为 json 表示
- 将 json 写入
Writer
- Returns 由 marshalling/writing 引起的任何错误
还有一件事,您可能对 Writer 是什么感到困惑,因为它不是数据类型,而是接口——这是一种数据类型的行为,一种类型实现的预定义方法。然后,任何实现 Write()
方法的东西都被认为是一个 writer。
初学者一开始可能有点难以掌握,但是网上有很多资源可以帮助理解界面(ReadWriters
是一些比较常见的界面,还有 Error()
(即所有错误))。