最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

談?wù)剬?duì)Golang IO讀寫(xiě)的困惑

 更新時(shí)間:2020年08月27日 10:10:15   作者:言淦  
這篇文章主要介紹了談?wù)剬?duì)Golang IO讀寫(xiě)的困惑,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

Golang的IO讀寫(xiě)提供了很多種方式,目前本人知道的有io庫(kù)、os庫(kù)、ioutil庫(kù)、bufio庫(kù)、bytes/strings庫(kù)等。

雖然庫(kù)多是一件好事,意味著選擇性多,但讓我困惑的一點(diǎn)是:什么場(chǎng)景下該用哪個(gè)庫(kù)? 為什么?

在給出結(jié)論前,我先想給出Golang內(nèi)置IO庫(kù)的項(xiàng)目結(jié)構(gòu),主要方便理解和引用:

# 只列舉了核心的目錄及文件
src:
 - bufio
  - bufio.go
 - bytes
  - buffer.go
  - reader.go
 - io
  - ioutil
   - ioutil.go
  - io.go
 - os
  - file.go
 - strings 
  - reader.go

1.io庫(kù)屬于底層接口定義庫(kù),其作用是是定義一些基本接口和一些基本常量,并對(duì)這些接口的作用給出說(shuō)明,常見(jiàn)的接口有Reader、Writer等。一般用這個(gè)庫(kù)只是為了調(diào)用它的一些常量,比如io.EOF。

2.ioutil庫(kù)包含在io目錄下,它的主要作用是作為一個(gè)工具包,里面有一些比較實(shí)用的函數(shù),比如 ReadAll(從某個(gè)源讀取數(shù)據(jù))、ReadFile(讀取文件內(nèi)容)、WriteFile(將數(shù)據(jù)寫(xiě)入文件)、ReadDir(獲取目錄)

3.os庫(kù)主要是跟操作系統(tǒng)打交道,所以文件操作基本都會(huì)跟os庫(kù)掛鉤,比如創(chuàng)建文件、打開(kāi)一個(gè)文件等。這個(gè)庫(kù)往往會(huì)和ioutil庫(kù)、bufio庫(kù)等配合使用

4.bufio庫(kù)可以理解為在io庫(kù)上再封裝一層,加上了緩存功能。它可能會(huì)和ioutil庫(kù)和bytes.Buffer搞混。
4.1 bufio VS ioutil庫(kù):兩者都提供了對(duì)文件的讀寫(xiě)功能,唯一的不同就是bufio多了一層緩存的功能,這個(gè)優(yōu)勢(shì)主要體現(xiàn)讀取大文件的時(shí)候(ioutil.ReadFile是一次性將內(nèi)容加載到內(nèi)存,如果內(nèi)容過(guò)大,很容易爆內(nèi)存)

4.2 bufio VS bytes.Buffer:兩者都提供一層緩存功能,它們的不同主要在于 bufio 針對(duì)的是文件到內(nèi)存的緩存,而 bytes.Buffer 的針對(duì)的是內(nèi)存到內(nèi)存的緩存(個(gè)人感覺(jué)有點(diǎn)像channel,你也可以發(fā)現(xiàn) bytes.Buffer 并沒(méi)有提供接口將數(shù)據(jù)寫(xiě)到文件)。

5.bytes和strings庫(kù):這兩個(gè)庫(kù)有點(diǎn)迷,首先它們都實(shí)現(xiàn)了Reader接口,所以它們的不同主要在于針對(duì)的對(duì)象不同,bytes針對(duì)的是字節(jié),strings針對(duì)的是字符串(它們的方法實(shí)現(xiàn)原理很相似)。另一個(gè)區(qū)別就是 bytes還帶有Buffer的功能,但是 strings沒(méi)提供。

注:關(guān)于Reader和Writer接口,可以簡(jiǎn)單理解為讀取源和寫(xiě)入源,即只要實(shí)現(xiàn)Reader里面的Read方法,這個(gè)東西就可以作為一個(gè)讀取源,里面可以包含數(shù)據(jù)并被我們讀??;Writer亦是如此。

以上就是個(gè)人的一些結(jié)論,下面會(huì)針對(duì)以上結(jié)論做進(jìn)一步說(shuō)明,如果有錯(cuò)誤的地方麻煩請(qǐng)留言指正,比心❤️!

窺探 io 庫(kù)

io庫(kù)比較常用的接口有三個(gè),分別是Reader,Writer和Close。

// Read方法會(huì)接收一個(gè)字節(jié)數(shù)組p,并將讀取到的數(shù)據(jù)存進(jìn)該數(shù)組,最后返回讀取的字節(jié)數(shù)n。
// 注意n不一定等于讀取的數(shù)據(jù)長(zhǎng)度,比如字節(jié)數(shù)組p的容量太小,n會(huì)等于數(shù)組的長(zhǎng)度
type Reader interface {
  Read(p []byte) (n int, err error)
}

// Write 方法同樣接收一個(gè)字節(jié)數(shù)組p,并將接收的數(shù)據(jù)保存至文件或者標(biāo)準(zhǔn)輸出等,返回的n表示寫(xiě)入的數(shù)據(jù)長(zhǎng)度。
// 當(dāng)n不等于len(p)時(shí),返回一個(gè)錯(cuò)誤。
type Writer interface {
  Write(p []byte) (n int, err error)
}

// 關(guān)閉操作
type Closer interface {
  Close() error
}

關(guān)于 Read 方法的具體實(shí)現(xiàn),可以在strings庫(kù)中看到:

// 定義一個(gè)Reader接口體
type Reader struct {
  s    string
  i    int64 // current reading index
  prevRune int  // index of previous rune; or < 0
}

// 通過(guò)NewReader方法得到 reader 對(duì)象,這里有個(gè)關(guān)鍵的地方是傳入的字符串被賦值到 s 變量中
func NewReader(s string) *Reader { 
 return &Reader{s, 0, -1} 
}

// Read方法: 核心是 copy 方法,參數(shù)b雖然是切片,但是copy方法會(huì)影響到它的底層數(shù)組
func (r *Reader) Read(b []byte) (n int, err error) {
  if r.i >= int64(len(r.s)) {
    return 0, io.EOF
  }
 r.prevRune = -1
 // 核心方法
  n = copy(b, r.s[r.i:])
  r.i += int64(n)
  return
}

窺探 ioutil 庫(kù)

上面提到,ioutil 庫(kù)就是一個(gè)工具包,里面主要是比較實(shí)用的函數(shù),比如ReadFile、WriteFile等,唯一需要注意的是它們都是一次性讀取和一次性寫(xiě)入,所以當(dāng)讀取的時(shí)候注意文件不能過(guò)大。

從文件讀取數(shù)據(jù):

func readByFile() {
  data, err := ioutil.ReadFile( "./lab8_io/file/test.txt")
  if err != nil {
    log.Fatal("err:", err)
    return
  }
  fmt.Println("data", string(data)) // hello world!
}

把數(shù)據(jù)寫(xiě)入到文件:

func writeFile() {
  err := ioutil.WriteFile("./lab8_io/file/write_test.txt", []byte("hello world!"), 0644)
  if err != nil {
    panic(err)
    return
  }
}

遍歷目錄:遍歷目錄有一個(gè)需要注意的是它的排序并不是自然排序方式。

窺探bufio庫(kù)

bufio 庫(kù)在上面也提到過(guò),它主要是在io庫(kù)上加了一層緩存的功能,以下是bufio讀取大文件的例子:

func readBigFile(filePath string) error {
  f, err := os.Open(filePath)
  defer f.Close()

  if err != nil {
    log.Fatal(err)
    return err
  }

  buf := bufio.NewReader(f)
  count := 0
  for {
    count += 1
    line, err := buf.ReadString('\n')
    line = strings.TrimSpace(line)
    if err != nil {
      return err
    }
  fmt.Println("line", line)
  // 這里是避免全部打印
    if count > 100 {
      break
    }
  }
  return nil
}

注:

1.bufio 的ReadLine/ReadBytes/ReadString/ReadSlice: ReadString和ReadBytes等同,ReadBytes和ReadLine都調(diào)用了ReadSlice

窺探bytes/strings庫(kù)

前面提過(guò),就單純實(shí)現(xiàn)Reader接口,bytes和strings底層函數(shù)的實(shí)現(xiàn)方式是差不多的,可以查看其源碼得證:

// bytes/reader.go
// Read implements the io.Reader interface.
func (r *Reader) Read(b []byte) (n int, err error) {
  if r.i >= int64(len(r.s)) {
    return 0, io.EOF
  }
  r.prevRune = -1
  n = copy(b, r.s[r.i:])
  r.i += int64(n)
  return
}

// strings/reader.go
func (r *Reader) Read(b []byte) (n int, err error) {
  if r.i >= int64(len(r.s)) {
    return 0, io.EOF
  }
  r.prevRune = -1
  n = copy(b, r.s[r.i:])
  r.i += int64(n)
  return
}

參考/推薦

詳解golang中bufio包的實(shí)現(xiàn)原理
Golang 超大文件讀取的兩個(gè)方案
https://gist.github.com/suntong/032173e96247c0411140

到此這篇關(guān)于談?wù)剬?duì)Golang IO讀寫(xiě)的困惑的文章就介紹到這了,更多相關(guān)Golang IO讀寫(xiě)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用golang實(shí)現(xiàn)封裝trycatch異常處理實(shí)例代碼

    利用golang實(shí)現(xiàn)封裝trycatch異常處理實(shí)例代碼

    Go語(yǔ)言追求簡(jiǎn)潔優(yōu)雅,所以go語(yǔ)言不支持傳統(tǒng)的 try…catch…finally 這種異常,最近發(fā)現(xiàn)了不錯(cuò)的trycatch包,下面這篇文章主要跟大家分享了關(guān)于利用golang實(shí)現(xiàn)封裝trycatch異常處理的實(shí)例代碼,需要的朋友可以參考下。
    2017-07-07
  • Go語(yǔ)言中的Slice學(xué)習(xí)總結(jié)

    Go語(yǔ)言中的Slice學(xué)習(xí)總結(jié)

    這篇文章主要介紹了Go語(yǔ)言中的Slice學(xué)習(xí)總結(jié),本文講解了Slice的定義、Slice的長(zhǎng)度和容量、Slice是引用類(lèi)型、Slice引用傳遞發(fā)生“意外”等內(nèi)容,需要的朋友可以參考下
    2014-11-11
  • golang:json 反序列化的[]和nil操作

    golang:json 反序列化的[]和nil操作

    這篇文章主要介紹了golang:json 反序列化的[]和nil操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Golang實(shí)現(xiàn)深拷貝reflect原理示例探究

    Golang實(shí)現(xiàn)深拷貝reflect原理示例探究

    這篇文章主要為大家介紹了Golang實(shí)現(xiàn)reflect深拷貝原理示例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Go語(yǔ)言中 Channel 詳解

    Go語(yǔ)言中 Channel 詳解

    Go 語(yǔ)言中的 channel 是實(shí)現(xiàn) goroutine 間無(wú)鎖通信的關(guān)鍵機(jī)制,他使得寫(xiě)多線(xiàn)程并發(fā)程序變得簡(jiǎn)單、靈活、觸手可得。下面就個(gè)人理解對(duì) channel 使用過(guò)程中應(yīng)該注意的地方進(jìn)行一個(gè)簡(jiǎn)要的總結(jié)。
    2018-10-10
  • golang語(yǔ)法使用的注意事項(xiàng)

    golang語(yǔ)法使用的注意事項(xiàng)

    這篇文章主要給大家介紹了關(guān)于golang語(yǔ)法使用的一些注意事項(xiàng),Golang是一種靜態(tài)類(lèi)型的編程語(yǔ)言,它支持基本的數(shù)據(jù)類(lèi)型,包括整型、浮點(diǎn)型、布爾型、字符串型,需要的朋友可以參考下
    2023-07-07
  • Go語(yǔ)言中TCP/IP網(wǎng)絡(luò)編程的深入講解

    Go語(yǔ)言中TCP/IP網(wǎng)絡(luò)編程的深入講解

    這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言中TCP/IP網(wǎng)絡(luò)編程的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • golang結(jié)構(gòu)體與json格式串實(shí)例代碼

    golang結(jié)構(gòu)體與json格式串實(shí)例代碼

    本文通過(guò)實(shí)例代碼給大家介紹了golang結(jié)構(gòu)體與json格式串的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-10-10
  • 一文完全掌握 Go math/rand(源碼解析)

    一文完全掌握 Go math/rand(源碼解析)

    這篇文章主要介紹了一文完全掌握 Go math/rand(源碼解析),本文可以幫助大家快速使用Go Rand.,感興趣的朋友跟隨小編一起看看吧
    2021-04-04
  • 聊聊golang中多個(gè)defer的執(zhí)行順序

    聊聊golang中多個(gè)defer的執(zhí)行順序

    這篇文章主要介紹了golang中多個(gè)defer的執(zhí)行順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-05-05

最新評(píng)論

临桂县| 龙胜| 双辽市| 防城港市| 祁连县| 新昌县| 南漳县| 临海市| 新邵县| 抚宁县| 阳山县| 邳州市| 弥渡县| 东光县| 金昌市| 理塘县| 梨树县| 河东区| 玉溪市| 巴林右旗| 新余市| 奉化市| 舒城县| 长葛市| 视频| 吉安县| 绥阳县| 盐亭县| 五华县| 淮滨县| 柘城县| 大兴区| 东明县| 新民市| 咸宁市| 图们市| 镇平县| 措美县| 青阳县| 甘泉县| 南漳县|