GO语言学习笔记(7)| 青训营笔记

204 阅读2分钟

[ go 与 golang | 青训营笔记]

这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天, 在学习了go的相关基础知识以后,可以说是初步的了解了go,我在这过程中也记录了一些自己的学习经验以及心得,与大家分享一下。

25. IO

Seek interface

type Seeker interface {
  Seek(offset int64, whence int) (int64, error)
}

offset是指针移动的偏移量

whence表示指针移动的方式

0 从数据的头部开始移动指针

1 从数据的当前指针位置开始移动指针

2 从数据的尾部移动指针

seek设置下一次读写操作的指针位置,每次的读写操作都是从指针位置开始的

Close interface

type Closer interface {
  Close() error
}

关闭文件

文件打开模块

O_RDONLY int = syscall.O_RDONLY // 只读
O_WRONLY int = syscall.O_WRONLY // 只写
O_RDWR   int = syscall.O_RDWR   // 读写
O_APPEND int = syscall.O_APPEND // 追加
O_CREATE int = syscall.O_CREAT  // 如果不存在就创建
O_EXCL   int = syscall.O_EXCL   // 文件必须不存在
O_SYNC   int = syscall.O_SYNC   // 同步io
O_TRUNC  int = syscall.O_TRUNC  // 打开时清空文件

读取文件

os.Open(name string) (file *File, err error)
ioutil.ReadFile(name string) ([]byte, error)
os.ReadFile(name string) ([]byte, error)
os.OpenFile(name string, flag int, perm FileMode) (*File, error)

一次性读

func main() {
  bs, err := os.ReadFile("./abc.txt")
  if err != nil {
    fmt.Printf("Read file error: %v\n", err)
    return
  }

  fmt.Printf("%s\n", bs)
}

分片读

func main() {
  file, err := os.Open("abc.txt")
  if err != nil {
    panic(err)
  }
  defer file.Close()

  for {
    buf := make([]byte, 32)
    _, err = file.Read(buf)
    if err == io.EOF {
      break
    }

    if err != nil {
      panic(err)
    }

    fmt.Printf("%s", buf)
  }
}

带缓冲读

func main() {
  file, err := os.Open("./abc.txt")
  if err != nil {
    fmt.Printf("Open file error: %v\n", err)
    return
  }
  defer file.Close()

  reader := bufio.NewReader(file)
  for {
    // 按行读取
    line, err := reader.ReadString('\n')
    if err == io.EOF {
      break
    }
    fmt.Print(line)
  }
}

光标操作

file, _ := os.Open("abc.txt")
defer file.Close()

// 开始位置前进5个字节
var whence = 0
var offset int64 = 5
pos, _ := file.Seek(offset, whence)
fmt.Println("Jump forward 5 bytes from start position:", pos)

// 当前位置回退2个字节
whence = 1
offset = -2
pos, _ = file.Seek(offset, whence)
fmt.Println("Jump back 2 bytes from current position:", pos)
}

分隔符读

func main() {
  file, _ := os.Open("abc.txt")
  defer file.Close()

  scanner := bufio.NewScanner(file)

  // 分隔函数,默认 bufio.ScanLines
  scanner.Split(bufio.ScanWords)

  for scanner.Scan() {
    fmt.Println(scanner.Text())
  }

  err := scanner.Err()
  if err != nil {
    panic(err)
  }
}

按行读

func main() {
  file, _ := os.Open("abc.txt")
  defer file.Close()

  scanner := bufio.NewScanner(file)

  // 分隔函数,默认 bufio.ScanLines
  scanner.Split(bufio.ScanWords)

  for scanner.Scan() {
    fmt.Println(scanner.Text())
  }

  err := scanner.Err()
  if err != nil {
    panic(err)
  }
}

写入文件

os.OpenFile(name string, flag int, perm FileMode) (file *File, err error)
os.Create(name string) (*File, error)
io/ioutil.Write(filename string, data []byte, perm fs.FileMode) error

文件操作模式:
覆盖写:os.O_WRONLY | os.O_TRUNC
追加写:os.O_WRONLY | os.O_APPEND
读写并追加:os.O_RDWR | os.OS_APPENDCopyErrorOK!

常规写

func writeFile() {
  file, err := os.OpenFile("abc.txt", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0644)
  if err != nil {
    panic(err)
  }
  defer file.Close()

  byteSlice := []byte("hello world!")
  bytesWritten, err := file.Write(byteSlice)
  if err != nil {
    panic(err)
  }
  fmt.Printf("Wrote %d bytes\n", bytesWritten)
}

快速写

func main() {
  err := ioutil.WriteFile("abc.txt", []byte("add a new line"), 0644)
  if err != nil {
    panic(err)
  }
}

缓冲写

func main() {
  file, err := os.OpenFile("abc.txt", os.O_CREATE|os.O_WRONLY, 0600)
  if err != nil {
        panic(err)
  }
  defer file.Close()

  msg := "Hello World!\n"

  writer := bufio.NewWriter(file)
  for i := 0; i < 5; i++ {
    writer.Write([]byte(msg))
  }
  writer.Flush()
}

复制文件

io.Copy(dst Writer, src Reader) (written int64, err error)CopyErrorOK!
read, _ := os.Open("xxx.jpg")
write, _ := os.Create("xx2.jpg")
n, err := io.Copy(write, read)
fmt.Println(n, err)CopyErrorOK!

目录操作

递归展示文件夹下所有文件

func readDir(path string) {
  dir, err := os.ReadDir(path)
  if err != nil {
    fmt.Println(err)
    return
  }

  for _, entry := range dir {
    name := entry.Name()
    nPath := fmt.Sprintf("%s/%s", path, name)
    if entry.IsDir() {
      readDir(nPath)
      continue
    }
    fmt.Println(nPath)

  }
}

26. 网络编程

TCP

服务端

package main

import (
  "fmt"
  "io"
  "net"
)

func main() {
  // 创建tcp的监听地址
  tcpAddr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
  // tcp监听
  listen, _ := net.ListenTCP("tcp", tcpAddr)
  for {
    // 等待连接
    conn, err := listen.AcceptTCP()
    if err != nil {
      fmt.Println(err)
      break
    }
    // 获取客户端的地址
    fmt.Println(conn.RemoteAddr().String() + " 进来了")
    // 读取客户端传来的数据
    for {
      var buf []byte = make([]byte, 1024)
      n, err := conn.Read(buf)
      // 客户端退出
      if err == io.EOF {
        fmt.Println(conn.RemoteAddr().String() + " 出去了")
        break
      }
      fmt.Println(string(buf[0:n]))
    }

  }

}

客户端

package main

import (
  "fmt"
  "net"
)

func main() {
  conn, _ := net.DialTCP("tcp", nil,
    &net.TCPAddr{
      IP:   net.ParseIP("127.0.0.1"),
      Port: 8080})
  var s string
  for {
    fmt.Scanln(&s)
    if s == "q" {
      break
    }
    conn.Write([]byte(s))
  }

  conn.Close()
}