Files
the-way-to-go_ZH_CN/eBook/12.8.md
Haigang Zhou d29644465a 第十二章修改 (#838)
Co-authored-by: Joe Chen <jc@unknwon.io>
2022-05-12 21:59:20 +08:00

112 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 12.8 使用接口的实际例子fmt.Fprintf
例子程序 `io_interfaces.go` 很好的阐述了 `io` 包中的接口概念。
示例 12.15 [io_interfaces.go](examples/chapter_12/io_interfaces.go)
```go
// interfaces being used in the GO-package fmt
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// unbuffered
fmt.Fprintf(os.Stdout, "%s\n", "hello world! - unbuffered")
// buffered: os.Stdout implements io.Writer
buf := bufio.NewWriter(os.Stdout)
// and now so does buf.
fmt.Fprintf(buf, "%s\n", "hello world! - buffered")
buf.Flush()
}
```
输出:
```
hello world! - unbuffered
hello world! - buffered
```
下面是 `fmt.Fprintf()` 函数的实际签名
```go
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
```
不是写入一个文件,而是写入一个 `io.Writer` 接口类型的变量,下面是 `Writer` 接口在 `io` 包中的定义:
```go
type Writer interface {
Write(p []byte) (n int, err error)
}
```
`fmt.Fprintf()` 依据指定的格式向第一个参数内写入字符串,第一个参数必须实现了 `io.Writer` 接口。`Fprintf()` 能够写入任何类型,只要其实现了 `Write` 方法,包括 `os.Stdout`,文件(例如 `os.File`),管道,网络连接,通道等等。同样地,也可以使用 `bufio` 包中缓冲写入。`bufio` 包中定义了 `type Writer struct{...}`
`bufio.Writer` 实现了 `Write()` 方法:
```go
func (b *Writer) Write(p []byte) (nn int, err error)
```
它还有一个工厂函数:传给它一个 `io.Writer` 类型的参数,它会返回一个带缓冲的 `bufio.Writer` 类型的 `io.Writer`
```go
func NewWriter(wr io.Writer) (b *Writer)
```
适合任何形式的缓冲写入。
在缓冲写入的最后千万不要忘了使用 `Flush()`,否则最后的输出不会被写入。
在 [15.2](15.2.md)-[15.8](15.8.md) 章节,我们将使用 `fmt.Fprint()` 函数向 `http.ResponseWriter` 写入,其同样实现了 `io.Writer` 接口。
**练习 12.7**[remove_3till5char.go](exercises/chapter_12/remove_3till5char.go)
下面的代码有一个输入文件 `goprogram`,然后以每一行为单位读取,从读取的当前行中截取第 3 到第 5 的字节写入另一个文件。然而当你运行这个程序,输出的文件却是个空文件。找出程序逻辑中的 bug修正它并测试。
```go
package main
import (
"bufio"
"fmt"
"os"
"io"
)
func main() {
inputFile, _ := os.Open("goprogram")
outputFile, _ := os.OpenFile("goprogramT", os.O_WRONLY|os.O_CREATE, 0666)
defer inputFile.Close()
defer outputFile.Close()
inputReader := bufio.NewReader(inputFile)
outputWriter := bufio.NewWriter(outputFile)
for {
inputString, _, readerError := inputReader.ReadLine()
if readerError == io.EOF {
fmt.Println("EOF")
return
}
outputString := string(inputString[2:5]) + "\r\n"
_, err := outputWriter.WriteString(outputString)
if err != nil {
fmt.Println(err)
return
}
}
fmt.Println("Conversion done")
}
```
## 链接
- [目录](directory.md)
- 上一节:[用 defer 关闭文件](12.7.md)
- 下一节:[格式化 JSON 数据](12.9.md)