TOC

Golang io

io, io/fs, io/util, os

find /usr/share/go-1.17/src/io/ -type f | grep -Fv _test.go
/usr/share/go-1.17/src/io/ioutil/testdata/hello
/usr/share/go-1.17/src/io/ioutil/tempfile.go
/usr/share/go-1.17/src/io/ioutil/ioutil.go
/usr/share/go-1.17/src/io/pipe.go
/usr/share/go-1.17/src/io/fs/fs.go
/usr/share/go-1.17/src/io/fs/readfile.go
/usr/share/go-1.17/src/io/fs/readdir.go
/usr/share/go-1.17/src/io/fs/sub.go
/usr/share/go-1.17/src/io/fs/stat.go
/usr/share/go-1.17/src/io/fs/walk.go
/usr/share/go-1.17/src/io/fs/glob.go
/usr/share/go-1.17/src/io/io.go
/usr/share/go-1.17/src/io/multi.go

方法

https://pkg.go.dev/io

相关方法

io.Reader / io.Writer

type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

stringsbytesbufioos.File 都是 io.Reader 的实现。

小技巧:利用类型断言检查是否实现指定接口

https://stackoverflow.com/a/25677274

var _ io.Reader = (*os.File)(nil)
// nil 可以转换成任意类型的空指针
// 这里将 nil 转换成 os.File 指针,再赋值给 io.Reader 类型

io/fs

func Glob(fsys FS, pattern string) (matches []string, err error)
func ReadFile(fsys FS, name string) ([]byte, error)
func ValidPath(name string) bool
func WalkDir(fsys FS, root string, fn WalkDirFunc) error

io/util 包 (原 ioutil)

1.6 以及之后新版本,iouitl 包依然保留,但是只是对 io 包的封装。

Package ioutil implements some I/O utility functions.
As of Go 1.16, the same functionality is now provided by package io or package os, and those implementations should be preferred in new code. See the specific function documentation for details.

  1. func NopCloser(r io.Reader) io.ReadCloser
  2. func ReadAll(r io.Reader) ([]byte, error)
  3. func ReadDir(dirname string) ([]fs.FileInfo, error)
  4. func ReadFile(filename string) ([]byte, error)
  5. func TempDir(dir, pattern string) (name string, err error)
  6. func TempFile(dir, pattern string) (f *os.File, err error)
  7. func WriteFile(filename string, data []byte, perm fs.FileMode) error
// grep -REv "^//" /usr/share/go-1.17/src/io/ioutil/tempfile.go
package ioutil

import (
        "os"
)

func TempFile(dir, pattern string) (f *os.File, err error) {
        return os.CreateTemp(dir, pattern)
}

func TempDir(dir, pattern string) (name string, err error) {
        return os.MkdirTemp(dir, pattern)
}
// grep -REv "^//" /usr/share/go-1.17/src/io/ioutil/ioutil.go
package ioutil

import (
        "io"
        "io/fs"
        "os"
        "sort"
)

func ReadAll(r io.Reader) ([]byte, error) {
        return io.ReadAll(r)
}

func ReadFile(filename string) ([]byte, error) {
        return os.ReadFile(filename)
}

func WriteFile(filename string, data []byte, perm fs.FileMode) error {
        return os.WriteFile(filename, data, perm)
}

func ReadDir(dirname string) ([]fs.FileInfo, error) {
        f, err := os.Open(dirname)
        if err != nil {
                return nil, err
        }
        list, err := f.Readdir(-1)
        f.Close()
        if err != nil {
                return nil, err
        }
        sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() })
        return list, nil
}

func NopCloser(r io.Reader) io.ReadCloser {
        return io.NopCloser(r)
}

var Discard io.Writer = io.Discard

引申

io 包是基础,提供了 Reader 和 Writer 接口。其他包则是实现这两个接口。

string 包:字符串 IO

相当于 Python io.StringIO

  • string.Reader

bytes 包:字节 IO

通过 []byte 模拟 io,相当于 Python io.BytesIO

  • bytes.Buffer (Reader + Writer)
  • bytes.Reader

buffio 包:缓冲 IO

就是加入了一个缓冲的功能,提升 IO 效率,减少直接系统调用。
也方便实现一些网络协议中的分包,比如 SMTP 协议中按换行切割。

  • bufio.Reader
  • bufio.Writer
package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("test.txt")
    if err != nil {
        fmt.Println("无法打开文件:", err)
        return
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            // 文件结束或发生错误
            break
        }
        fmt.Print(line)
    }
}

os 包:系统 IO

  • os.File 文件类型
func Open(name string) (*File, error)
func OpenFile(name string, flag int, perm FileMode) (*File, error)

var Stdin = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
var Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
var Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")

net 包:网络 IO

网络编程的部分,这里就不继续展开了。

  • net.Conn 网络连接
func Pipe() (Conn, Conn)

func Dial(network, address string) (Conn, error)
func DialTimeout(network, address string, timeout time.Duration) (Conn, error)
func FileConn(f *os.File) (c Conn, err error)

func (d *Dialer) Dial(network, address string) (Conn, error)
func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn, error)

func FilePacketConn(f *os.File) (c PacketConn, err error)
func ListenPacket(network, address string) (PacketConn, error)

func DialIP(network string, laddr, raddr *IPAddr) (*IPConn, error)
func ListenIP(network string, laddr *IPAddr) (*IPConn, error)

func DialTCP(network string, laddr, raddr *TCPAddr) (*TCPConn, error)
func (l *TCPListener) Accept() (Conn, error)
func (l *TCPListener) AcceptTCP() (*TCPConn, error)

func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error)
func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error)
func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)

func DialUnix(network string, laddr, raddr *UnixAddr) (*UnixConn, error)
func ListenUnixgram(network string, laddr *UnixAddr) (*UnixConn, error)
func (l *UnixListener) Accept() (Conn, error)
func (l *UnixListener) AcceptUnix() (*UnixConn, error)