1. 常用方法和函数

  1. ## os 模块
  2. 1. File结构体
  3. Syntax: type File struct { }
  4. Man: 文件对象
  5. 2. Open()
  6. Syntax: func Open(name string) (file *File, err error)
  7. Man: Open打开一个文件用于读取,对应的文件描述符具有O_RDONLY模式
  8. 3. OpenFile()
  9. Syntax: func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
  10. Man: 打开文件,可以指定打开方式、权限等。一般应用于写文件的场景
  11. flag使用位运算中的 | 拼接:
  12. const (
  13. O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
  14. O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
  15. O_RDWR int = syscall.O_RDWR // 读写模式打开文件
  16. O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
  17. O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
  18. O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
  19. O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
  20. O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
  21. )
  22. permLinux下文件权限,如 0644, 0400
  23. 3. Close()
  24. Syntax: func (f *File) Close() error
  25. Man: Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。
  26. 4. Name()
  27. Syntax: func (f *File) Name() string
  28. Man: Name方法返回(提供给Open/Create等方法的)文件名称
  29. ## bufio模块
  30. 1. Reader结构体
  31. Syntax: type Reader struct { }
  32. Man: Reader实现了给一个io.Reader接口对象附加缓冲
  33. 2. NewReader()
  34. Syntax: func NewReader(rd io.Reader) *Reader
  35. Man: 创建默认缓冲区大小的 Reader 对象指针,默认为 2048
  36. 3. NewReaderSize()
  37. Syntax: func NewReaderSize(rd io.Reader, size int) *Reader
  38. Man: 创建指定缓冲区大小的 Reader 对象指针
  39. 4. ReadString()
  40. Syntax: func (b *Reader) ReadString(delim byte) (line string, err error)
  41. Man: ReadString读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的字符串。
  42. 如果ReadString方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。
  43. 当且仅当ReadString方法返回的切片不以delim结尾时,会返回一个非nil的错误。
  44. 5. ReadBytes()
  45. Syntax: func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
  46. Man: ReadBytes读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的切片。
  47. 如果ReadBytes方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。
  48. 当且仅当ReadBytes方法返回的切片不以delim结尾时,会返回一个非nil的错误。
  49. 6. NewWriter()
  50. Syntax: func NewWriter(w io.Writer) *Writer
  51. Man: NewWriter创建一个具有默认大小缓冲、写入w的*Writer
  52. 7. NewWriterSize()
  53. Syntax: func NewWriterSize(w io.Writer, size int) *Writer
  54. Man: NewWriterSize创建一个具有最少有size尺寸的缓冲、写入w的*Writer
  55. 8. WriteString()
  56. Syntaxfunc (b *Writer) WriteString(s string) (int, error)
  57. Man: WriteString写入一个字符串,返回写入的字节数。
  58. 9. Write()
  59. Syntax: func (b *Writer) Write(p []byte) (nn int, err error)
  60. Man: Writep的内容写入缓冲。返回写入的字节数。如果返回值nn < len(p),还会返回一个错误说明原因。
  61. 10. Flush()
  62. Syntax: func (b *Writer) Flush() error
  63. Man: 刷盘,将系统缓冲区内容写入文件
  64. ## ioutil模块
  65. 1. ReadFile()
  66. Syntax: func ReadFile(filename string) ([]byte, error)
  67. Man: ReadFile filename指定的文件中读取数据并返回文件的内容。成功的调用返回的errnil而非EOF
  68. 2. WriteFile()
  69. Syntax: func WriteFile(filename string, data []byte, perm os.FileMode) error
  70. Man: 函数向filename指定的文件中写入数据。
  71. 如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。

2. 读文件

2.1. 带缓冲区的方式读取文件

使用缓冲区的方式读取文件内容,适合文件较大的情况或者文件大小未知的情况,避免一次性占用太多内存。

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "os"
  7. )
  8. func main() {
  9. file, err := os.Open("/etc/passwd")
  10. if err != nil {
  11. fmt.Printf("读取文件失败,err: %v\n", err)
  12. return
  13. }
  14. defer file.Close()
  15. // 使用缓冲区的方式读取文件内容,适合文件内容较大的情况,避免一次性占用太多内存
  16. reader := bufio.NewReaderSize(file, 2048)
  17. for {
  18. str, err := reader.ReadString('\n')
  19. if err == io.EOF {
  20. break
  21. } else if err != nil {
  22. fmt.Println("文件读取异常,err=", err)
  23. } else {
  24. fmt.Print(str)
  25. }
  26. }
  27. }

2.2. 一次性读取文件内容

一次性读取文件内容,适合小文件,如配置文件等。

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. // 一次性读取文件内容,适合小文件,如配置文件等
  8. if content, err := ioutil.ReadFile("/etc/passwd"); err != nil {
  9. fmt.Println("文件读取失败")
  10. } else {
  11. fmt.Print(string(content))
  12. }
  13. }

3. 写文件

3.1. 带缓冲的方式写文件

使用带缓冲的方式写文件实际运用场景比较多,需要注意的以下问题:

  • 必须要关闭文件前使用 writer.Flush() ,否则可能导致写入的文件内容不全
  • 写入字节切片 []bytestring 是一样的效果,不会出现中文乱码问题
  • 在Linux下,如果当前用户对文件没有写入权限如0400权限下,会提示 permission denied
  • 写文件时是覆盖还是追加,取决于打开文件时使用的 flag

    3.1.1. 追加文件内容

    ```go package main

import ( “bufio” “fmt” “os” )

func main() { file, err := os.OpenFile(“test.txt”, os.OWRONLY | os.O_CREATE | os.O_APPEND, 0600) if err != nil { fmt.Println(“打开文件失败; err=”,err) return } defer func() { = file.Close() }() // 使用缓冲的方式写字符串到文件 writer := bufio.NewWriter(file) for i:=0; i<3; i++ { if , err := writer.WriteString(“Hello 北京”+”\n”); err != nil { fmt.Println(“文件写入失败, err=”, err) break } } // 使用缓冲的方式写byte切片到文件 sli := []byte(“Hello 北京\n”) for i:=0; i< 3; i++ { if , err := writer.Write(sli); err != nil { fmt.Println(“文件写入失败, err=”, err) break } } _ = writer.Flush() }

  1. <a name="yK6iF"></a>
  2. #### 3.1.1. 覆盖文件内容
  3. 想要覆盖文件,必须要添加 `os.O_TRUNC` ,否则会和原有内容重叠。
  4. ```go
  5. package main
  6. import (
  7. "bufio"
  8. "fmt"
  9. "os"
  10. )
  11. func main() {
  12. file, err := os.OpenFile("test.txt", os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0600)
  13. if err != nil {
  14. fmt.Println("打开文件失败; err=",err)
  15. return
  16. }
  17. defer func() {
  18. _ = file.Close()
  19. }()
  20. for i:=0; i<3; i++ {
  21. if _, err := writer.WriteString("Hello 南京"+"\n"); err != nil {
  22. fmt.Println("文件写入失败, err=", err)
  23. break
  24. }
  25. }
  26. _ = writer.Flush()
  27. }

3.2. 一次性写文件

一次性写入文件内容,比如调用go生成k8s的清单文件等。

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. )
  6. func main() {
  7. err := ioutil.WriteFile("go.txt", []byte("Golang 不难!"), 0400)
  8. if err != nil {
  9. fmt.Println("文件写入失败,err=", err)
  10. }
  11. }

3.3. 判断文件是否存在并写入

在下面的案例中,由于涉及 ssh-key,因此覆写时,需要修改文件权限,避免写入失败!

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. )
  7. func FileIsExist(filename string) (bool, error) {
  8. if _, err := os.Stat(filename); err == nil {
  9. _ = os.Chmod("go.txt", 0600)
  10. return true, nil
  11. } else if os.IsNotExist(err) {
  12. return false, nil
  13. } else {
  14. return false, err
  15. }
  16. }
  17. func main() {
  18. if flag, _ := FileIsExist("go.txt"); ! flag {
  19. fmt.Println("文件不存在")
  20. return
  21. }
  22. if err := ioutil.WriteFile("go.txt", []byte("ssh-key"), 0400); err != nil {
  23. fmt.Println("文件写入失败,err=",err)
  24. }
  25. }