io包
简介
io包提供了系统io最基本的封装,可以用来进行文件的读取,写入,复制等功能。不是线程安全的。
思维导图概览
由于思维导图比较大,这边就不放图了,提供两种途径观看
功能
上面思维导图中虽然方法,接口一大堆,但是我们正常用的话用下面的几个函数就可以了,这几个函数也是对io包里的方法进一步封装。
复制
func Copy
func Copy(dst Writer, src Reader) (written int64, err error)
这个函数可以进行文件夹的复制功能,dest参数是目标文件,src参数是源文件。可以实现src文件复制到dst文件的功能。返回值written是复制文件的大小
代码示例:
将
字符串流复制到了系统输出流里,然后输出了复制的数据大小
package main
import (
"fmt"
"io"
"os"
"strings"
)
func main() {
src:=strings.NewReader("这是源文件字符串流")
l,_:=io.Copy(os.Stdout,src)
fmt.Printf("\n复制的数据大小:%d",l)
}
输出:
这是源文件字符串流
复制的数据大小:27
func CopyBuffer
func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
CopyBuffer与Copy相同,区别在于CopyBuffer使用提供的缓冲区,可以自定义缓冲区大小,而不是分配一个临时缓冲区。如果buf为nil,则分配一个临时缓冲区(func Copy就是调用了这个函数,然后buf传了nil);如果长度为0,则CopyBuffer会报异常。
代码示例:自定义大小为
100字节的缓冲区,然后将字符串流复制到了系统输出流里,然后输出了复制的数据大小
package main
import (
"fmt"
"io"
"os"
"strings"
)
func main() {
src:=strings.NewReader("这是源文件字符串流")
buf:=make([]byte,100)
l,_:=io.CopyBuffer(os.Stdout,src,buf)
fmt.Printf("\n复制的数据大小:%d",l)
}
输出:
这是源文件字符串流
复制的数据大小:27
func CopyN
func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
这个函数可以自定义复制的流大小n,底层实现是先调用LimitReader函数,然后将结果作为src再复制到dest上。
代码示例:复制7个字节的数据到
系统输出流,然后输出已复制的数据大小
package main
import (
"fmt"
"io"
"os"
"strings"
)
func main() {
src:=strings.NewReader("this is test!")
l,_:=io.CopyN(os.Stdout,src,7)
fmt.Printf("\n复制的数据大小:%d",l)
}
输出:
this is
复制的数据大小:7
读取
func ReadAll
func ReadAll(r Reader) ([]byte, error)
读取r的全部字节,然后返回[]byte
示例代码:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
src:=strings.NewReader("this is test!")
b,_:=io.ReadAll(src)
fmt.Printf("读取的字符串:%s",b)
}
输出:
读取的字符串:this is test!
func ReadAtLeast
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
- 参数
r表示要读取的io流 - 参数
buf是自定义的缓冲区,也是数据接收区 - 参数
min表示最少要读取的字节数
这个函数会根据你传入的buf大小来读取多少数据。比如你传入的buf的大小为4个字节,这个方法就只会从r中读取4个字节的数据
注意:自定义缓冲区
buf要大于最小读取字节数min。如果自定义缓冲区小于等于最小读取字节数min,则会发生异常
代码示例:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
src:=strings.NewReader("this is test!")
buf:=make([]byte,4)
l,_:=io.ReadAtLeast(src,buf,2)
fmt.Printf("读取的数据:%s\n",buf)
fmt.Printf("读取的字节数:%d",l)
}
输出:
读取的数据:this
读取的字节数:4
func ReadFull
func ReadFull(r Reader, buf []byte) (n int, err error)
这个函数功能和ReadAtLeast函数一样,而且内部就是调用了这个函数,只是ReadAtLeast的min值就是buf的长度。
所以这个函数的功能也是根据你传入的buf大小来读取多少数据。
写入
func WriteString
func WriteString(w Writer, s string) (n int, err error)
- 参数
w是要写入的目标流 - 参数
s是要写入的字符串数据 这个函数的功能是将字符串s写入到w流中,然后返回写入的数据大小n
package main
import (
"fmt"
"io"
"os"
)
func main() {
l,_:=io.WriteString(os.Stdout,"go test!")
fmt.Printf("\n写入的数据大小:%d",l)
}
输出:
go test!
写入的数据大小:8
同步管道流
func pipe
func Pipe() (*PipeReader, *PipeWriter)
这个函数提供了一个安全读取流的功能,调用这个函数后,会返回一个写入流,一个读取流。当未读取*PipeReader里的数据时,*PipeWriter始终为阻塞状态,而当读取*PipeReader里的数据时,*PipeReader就变为阻塞状态,期间不能往管道里写入数据。
也就是说这个是线程安全的方法,在任一时刻,要么只能读取数据,要么只能写入数据。
package main
import (
"fmt"
"io"
"os"
"time"
)
func main() {
r, w := io.Pipe()
go func() {
io.WriteString(w,"go pip test")
io.WriteString(w,"\ngo test2")
// 调用`Close`方法代表数据写入完成,释放写锁
w.Close()
}()
fmt.Println("2秒后开始准备读取数据")
time.Sleep(2*time.Second)
io.Copy(os.Stdout, r)
}
输出:
2秒后开始准备读取数据
go pip test
go test2