go标准包系列-io

1 IO包

​ Go 语言的 “io” 标准库包是一个用于处理 I/O(输入/输出)操作的库。它提供了一组接口和实现,用于从不同来源读取和写入数据。这个包的核心概念是 Reader 和 Writer 接口,它们分别用于从不同来源读取数据和将数据写入不同的目标

1.1 Reader 接口

​ 定义了用于读取数据的基本方法。最重要的方法是 Read,它接受一个字节切片作为参数,并将数据填充到这个切片中。Read 方法返回读取的字节数和可能遇到的错误。

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

用法:

func ReadFrom(reader io.Reader, num int) ([]byte, error) {
    p := make([]byte, num)
    n, err := reader.Read(p)
    if n > 0 {
        return p[:n], nil
    }
    return p, err
}
1.2 Writer 接口

​ 定义了用于写入数据的基本方法。最重要的方法是 Write,它接受一个字节切片作为参数,并将数据写入目标。Write 方法返回写入的字节数和可能遇到的错误

type Writer interface {
    Write(p []byte) (n int, err error)
}
1.3 ReaderAt 和 WriterAt 接口
type ReaderAt interface {
    ReadAt(p []byte, off int64) (n int, err error)
}
type WriterAt interface {
    WriteAt(p []byte, off int64) (n int, err error)
}
1.4 ReaderFrom 和 WriterTo 接口
type ReaderFrom interface {
    ReadFrom(r Reader) (n int64, err error)
}
type WriterTo interface {
    WriteTo(w Writer) (n int64, err error)
}

2 io/ioutil包 (1.16后废弃)

2.1 ReadAll

​ 用于从 io.Reader 中读取所有数据到字节切片。在 Go 1.16 之后,请使用 “io” 包中的 “io.ReadAll” 函数代替。

// ioutil.ReadAll

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

// io.ReadAll (Go 1.16+)

func ReadAll(r io.Reader) ([]byte, error)
2.2 ReadFile

​ 用于一次性读取整个文件内容到字节切片。在 Go 1.16 之后,请使用 “os” 包中的 “os.ReadFile” 函数代替。

// ioutil.ReadFile

func ReadFile(filename string) ([]byte, error)

// os.ReadFile (Go 1.16+)

func ReadFile(name string) ([]byte, error)
2.3 WriteFile

​ 用于一次性将字节切片写入文件。在 Go 1.16 之后,请使用 “os” 包中的 “os.WriteFile” 函数代替。

// ioutil.WriteFile

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

// os.WriteFile (Go 1.16+)

func WriteFile(name string, data []byte, perm FileMode) error
2.4 TempFile

​ 用于在指定目录创建一个临时文件。在 Go 1.16 之后,请使用 “os” 包中的 “os.CreateTemp” 函数代替。

// ioutil.TempFile

func TempFile(dir, pattern string) (f *os.File, err error)

// os.CreateTemp (Go 1.16+)

func CreateTemp(dir, pattern string) (*File, error)
2.5 TempDir

​ 用于在指定目录创建一个临时目录。在 Go 1.16 之后,请使用 “os” 包中的 “os.MkdirTemp” 函数代替。

// ioutil.TempDir

func TempDir(dir, pattern string) (name string, err error)

// os.MkdirTemp (Go 1.16+)

func MkdirTemp(dir, pattern string) (string, error)

3 fmt包

3.1 Printing

%d    十进制表示

%f    有小数点而无指数,例如 123.456    

%s    输出字符串表示(string类型或[]byte) 

%p    十六进制表示,前缀 0x  

%t    单词 truefalse

3.2 Scanning

%p 没有实现

%T 没有实现

%d 十进制表示

%f 有小数点而无指数,例如 123.456

%s 输出字符串表示(string类型或[]byte)

%p 十六进制表示,前缀 0x

%t 单词 true 或 false。
3.3 Print 序列函数

Fprint/Fprintf/Fprintln/Sprint/Sprintf/Sprintln/Print/Printf/Println

一般的,我们将 Fprint/Fprintf/Fprintln 归为一类;Sprint/Sprintf/Sprintln 归为一类;Print/Printf/Println 归为另一类。

  • Fprint/Fprintf/Fprintln 函数的第一个参数接收一个io.Writer类型,会将内容输出到 io.Writer 中去
  • Sprint/Sprintf/Sprintln 是格式化内容为 string 类型,而并不输出到某处,需要格式化字符串并返回时,可以用这组函数
  • Print/Printf/Println 函数是将内容输出到标准输出中

其中,Print/Printf/Println 会调用相应的F开头一类函数,并将 os.Stdout 作为第一个参数传入。如:

    func Print(a ...interface{}) (n int, err error) {
        return Fprint(os.Stdout, a...)
    }
3.4 Stringer 接口

Stringer接口的定义如下:

    type Stringer interface {
        String() string
    }

根据 Go 语言中实现接口的定义,一个类型只要有 String() string 方法,我们就说它实现了 Stringer 接口。而在本节开始已经说到,如果格式化输出某种类型的值,只要它实现了 String() 方法,那么会调用 String() 方法进行处理。

接下来,为Person增加String方法。

    func (this *Person) String() string {
        buffer := bytes.NewBufferString("This is ")
        buffer.WriteString(this.Name + ", ")
        if this.Sex == 0 {
            buffer.WriteString("He ")
        } else {
            buffer.WriteString("She ")
        }

        buffer.WriteString("is ")
        buffer.WriteString(strconv.Itoa(this.Age))
        buffer.WriteString(" years old.")
        return buffer.String()
    }
	 type Person struct {
        Name string
        Age  int
        Sex  int
    }
 	p := &Person{"polaris", 28, 0}
    fmt.Println(p)
3.5 Formatter 接口

Formatter 接口的定义如下:

    type Formatter interface {
        Format(f State, c rune)
    }

Formatter 接口由带有定制的格式化器的值所实现。 Format 的实现可调用Printf/ Sprintf / Fprintf(f) 等函数来生成其输出。

具体实例如下

    func (this *Person) Format(f fmt.State, c rune) {
        if c == 'L' {
            f.Write([]byte(this.String()))
            f.Write([]byte(" Person has three fields."))
        } else {
            // 没有此句,会导致 fmt.Printf("%s", p) 啥也不输出
            f.Write([]byte(fmt.Sprintln(this.String())))
        }
    }
	p := &Person{"polaris", 28, 0}
    fmt.Printf("%L", p)
3.6 GoStringer 接口

GoStringer 接口定义如下;

    type GoStringer interface {
        GoString() string
    }

该接口定义了类型的Go语法格式。用于打印(Printf)格式化占位符为 %#v 的值。

    func (this *Person) GoString() string {
        return "&Person{Name is "+this.Name+", Age is "+strconv.Itoa(this.Age)+", Sex is "+strconv.Itoa(this.Sex)+"}"
    }
	p := &Person{"polaris", 28, 0}
    fmt.Printf("%#v", p)
3.7 Scan 序列函数

Fscan/Fscanf/Fscanln/Sscan/Sscanf/Sscanln/Scan/Scanf/Scanln。

一般的,我们将Fscan/Fscanf/Fscanln归为一类;Sscan/Sscanf/Sscanln归为一类;Scan/Scanf/Scanln归为另一类。

Fscan/Fscanf/Fscanln 函数的第一个参数接收一个 io.Reader 类型,从其读取内容并赋值给相应的实参

Sscan/Sscanf/Sscanln 则直接从字符串中获取内容。

Scan/Scanf/Scanln 正是从标准输入获取内容

其中,Scan/Scanf/Scanln会调用相应的F开头一类函数,并将 os.Stdin 作为第一个参数传入。如:

func Scan(a ...interface{}) (n int, err error) {
        return Fscan(os.Stdin, a...)
    }
Scan/FScan/Sscan
 var (
        name string
        age  int
    )
    n, _ := fmt.Sscan("polaris 28", &name, &age)
    // 可以将"polaris 28"中的空格换成"\n"试试
    // n, _ := fmt.Sscan("polaris\n28", &name, &age)
    fmt.Println(n, name, age)

不管"polaris 28"是用空格分隔还是"\n"分隔,输出一样。也就是说,Scan/FScan/Sscan 这组函数将连续由空格分隔的值存储为连续的实参(换行符也记为空格)。

Scanf/FScanf/Sscanf
   var (
        name string
        age  int
    )
    n, _ := fmt.Sscanf("polaris 28", "%s%d", &name, &age)
    // 可以将"polaris 28"中的空格换成"\n"试试
    // n, _ := fmt.Sscanf("polaris\n28", "%s%d", &name, &age)
    fmt.Println(n, name, age)

如果将"空格"分隔改为"\n"分隔,则输出为:1 polaris 0。可见,Scanf/FScanf/Sscanf 这组函数将连续由空格分隔的值存储为连续的实参, 其格式由 format 决定,换行符处停止扫描(Scan)。

Scanln/FScanln/Sscanln
  var (
        name string
        age  int
    )
    n, _ := fmt.Sscanln("polaris 28", &name, &age)
    // 可以将"polaris 28"中的空格换成"\n"试试
    // n, _ := fmt.Sscanln("polaris\n28", &name, &age)
    fmt.Println(n, name, age)

Scanln/FScanln/Sscanln表现和上一组一样,遇到"\n"停止(对于Scanln,表示从标准输入获取内容,最后需要回车)。

一般地,我们使用 Scan/Scanf/Scanln 这组函数。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值