欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Golang實(shí)現(xiàn)超時(shí)機(jī)制讀取文件的方法示例

 更新時(shí)間:2025年01月10日 10:55:15   作者:夢(mèng)想畫家  
讀寫文件是Go程序的基本任務(wù),包括使用程序查看文件內(nèi)容、創(chuàng)建或修改文件,Go提供了os,ioutil,io以及bufio包實(shí)現(xiàn)文件操作,本文介紹如果在讀文件過程中增加超時(shí)機(jī)制,避免文件太大一直占用資源,需要的朋友可以參考下

協(xié)程與通道

協(xié)程(Goroutine)是輕量級(jí)線程,可實(shí)現(xiàn)函數(shù)或方法與主程序流并行執(zhí)行。使用go關(guān)鍵字:go func(){}。通道是協(xié)程直接的通訊管道,主要用于在協(xié)程間傳輸數(shù)據(jù),即往通道寫數(shù)據(jù)、從通道讀數(shù)據(jù)。

通過chan關(guān)鍵字聲明通道,可以使用var或:=兩種方式聲明,也可以聲明待緩存的通道,語法如下:

channelName:= make(chan Type, n)

舉例:

dataStream := make(chan string, 1)

往通道寫數(shù)據(jù):

dataStream <- "data"

從通道讀數(shù)據(jù):

varName := <-dataStream

關(guān)閉通道:

close(dataStream)

Go 超時(shí)機(jī)制

超時(shí)對(duì)于連接到外部資源或需要限制執(zhí)行時(shí)間的場景來說非常重要。這是因?yàn)樘L的服務(wù)器端處理將消耗太多的資源,導(dǎo)致并發(fā)性下降,甚至服務(wù)不可用。

利用select語句及并行協(xié)程實(shí)現(xiàn)超時(shí),必須導(dǎo)入time包。然后使用time.After()參數(shù)創(chuàng)建通道,調(diào)用time.After(1 * time.Second)將在1秒后填充通道。下面示例通過通道和select實(shí)現(xiàn)超時(shí):

package main
import (
    "fmt"
    "time"
)
func main() {
    dataChannel:= make(chan string, 1)

    go func() {
        time.Sleep(2 * time.Second)
        dataChannel <- "result 1"
    }()

    select {
        case results := <- dataChannel:
            fmt.Println(results)
        case <-time.After(1 * time.Second):
            fmt.Println("timeout 1")
    }
}

首先創(chuàng)建緩存通道dataChannel,調(diào)用函數(shù)模擬復(fù)雜業(yè)務(wù),2秒后從非阻塞通道返回結(jié)果。select語句實(shí)現(xiàn)超時(shí)。results := <- dataChannel等待結(jié)果,time.After(1 * time.Second)語句1秒后返回值,因此select首先等待1秒,超過1秒將超時(shí)。

下面利用該機(jī)制實(shí)現(xiàn)讀取文件超時(shí)機(jī)制實(shí)現(xiàn)。

讀取整個(gè)文件

Go中讀整個(gè)文件一般使用ioutil/os包中的Read File()函數(shù),讀取整個(gè)文件值字節(jié)slice。ioutil包最好別用于讀取大文件,對(duì)于小文件完全夠用。

os包包含執(zhí)行參數(shù)數(shù)組Args,包括執(zhí)行命令的所有參數(shù),為字符串類型數(shù)組。

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"time"
)

func main() {

	filePath := os.Args[1]
	timeOut, _ := strconv.ParseFloat(os.Args[2], 64)

	// buffered channel of dataStream
	dataStream := make(chan string, 1)
	// Run ReadFileToString function in it's own goroutine and pass back it's
	// response into dataStream channel.
	go func() {
		data, _ := ReadFileToString(filePath)
		dataStream <- data
		close(dataStream)
	}()

	// Listen on dataStream channel AND a timeout channel - which ever happens first.
	select {
	case res := <-dataStream:
		fmt.Println(res)
	case <-time.After(time.Duration(timeOut) * time.Second):
		fmt.Println("Program execution out of time ")
	}
}
func ReadFileToString(file string) (string, error) {
	content, err := ioutil.ReadFile(file)
	// error encountered during reading the data
	if err != nil {
		return "", err
	}
	// convert bytes to string
	return string(content), nil
}

我們可以使用不同的超時(shí)時(shí)間進(jìn)行測試:

go run main.go text.txt 1.0

go run main.go text.txt 0.9

按行讀文件

可以使用 bufio.Scanner 按行讀文件,使用bufio.NewScanner(file)構(gòu)造函數(shù)創(chuàng)建Scanner,然后通過Scan()和Text()方法逐行讀取內(nèi)容。使用Err()方法檢查讀取文件過程中的錯(cuò)誤。

package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"
)

func main() {
	//get filepath and timeout on the terminal
	filePath := os.Args[1]
	timeOut, _ := strconv.ParseFloat(os.Args[2], 64)
	//creating  channels
	dataStream := make(chan string, 1)
	readerr := make(chan error)

	// Run ReadFileLineByLine function in its own goroutine and pass back it's
	// response into dataStream channel.
	go ReadFileLineByLine(filePath, dataStream, readerr)

loop:
	for {
		// select statement will block this thread until one of the three conditions below is met

		select {
		case data := <-dataStream:
			// Process each line
			fmt.Println(data)
		case <-time.After(time.Duration(timeOut) * time.Second):
			fmt.Println("Program execution out of time ")
			break loop
		case err := <-readerr:
			if err != nil {
				log.Fatal(err)
			}
			break loop
		}
	}
}

func ReadFileLineByLine(filePath string, data chan string, er chan error) {
	// open file
	file, err := os.Open(filePath)
	if err != nil {
		fmt.Println(err)
	}
	// close the file at the end of the program
	defer file.Close()

	// read the file line by line using scanner
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		data <- scanner.Text()
	}
	close(data) // close causes the range on the channel to break out of the loop
	er <- scanner.Err()
}

當(dāng)然也可以使用不同超時(shí)時(shí)間進(jìn)行測試,如超時(shí)場景:

go run main.go test.txt 0.1
# Program execution out of time

按塊方式讀文件

對(duì)于非常大的文件使用塊方式讀取非常有用,無需把整個(gè)文件加載到內(nèi)存中,每次讀取固定塊大小內(nèi)容。下面readFileChunk函數(shù)中需要?jiǎng)?chuàng)建緩沖區(qū),每次讀取該緩沖區(qū)大小的內(nèi)容,直到io.EOF錯(cuò)誤出現(xiàn),表明已經(jīng)到達(dá)文件結(jié)尾。

緩沖區(qū)大小、目標(biāo)文件以及超時(shí)時(shí)間作為函數(shù)參數(shù),其他邏輯與上面示例一致:

package main

import (
   "fmt"
   "io"
   "log"
   "os"
   "strconv"
   "time"
)

func main() {
   dataStream := make(chan string, 1)
   filePath := os.Args[1]
   timeOut, _ := strconv.ParseFloat(os.Args[2], 64)
   chunkSize, _ := strconv.Atoi(os.Args[3])
   go readFileChunk (filePath, dataStream, int64(chunkSize))
   select {
   case resultData := <- dataStream:
      fmt.Println(resultData)
   case <-time.After(time.Duration(timeOut) * time.Millisecond):
      fmt.Println("timeout")
   }

}

func readFileChunk(filePath string, data chan string, chunkSize int64) {
   // open file
   f, err := os.Open(filePath)
   if err != nil {
      log.Fatal(err)
   }
   // remember to close the file at the end of the program
   defer f.Close()

   buf := make([]byte, chunkSize)
   for {
      readTotal, err := f.Read(buf)
      if err != nil && err != io.EOF {
         log.Fatal(err)
      }

      if err == io.EOF {
         break
      }

      data <- string(buf[:readTotal])
   }
   close(data)
}

總結(jié)

對(duì)于資源密集型程序正在執(zhí)行時(shí),Golang超時(shí)機(jī)制是必要的,它有助于終止這種冗長的程序。本文通過示例展示了不同方式讀取文件的超時(shí)機(jī)制實(shí)現(xiàn)。

到此這篇關(guān)于Golang實(shí)現(xiàn)超時(shí)機(jī)制讀取文件的方法示例的文章就介紹到這了,更多相關(guān)Golang超時(shí)機(jī)制讀取文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang使用embed引入靜態(tài)文件的實(shí)例代碼

    Golang使用embed引入靜態(tài)文件的實(shí)例代碼

    Golang embed是Go 1.16版本中引入的一項(xiàng)新功能,它可以使嵌入文件更容易,通常,在Go中嵌入文件需要使用文件系統(tǒng)或者第三方包,而使用embed可以更加便捷地嵌入文件,從而方便地訪問文件的內(nèi)容,本文介紹了Golang使用embed引入靜態(tài)文件,需要的朋友可以參考下
    2024-06-06
  • 在Go中編寫測試代碼的方法總結(jié)

    在Go中編寫測試代碼的方法總結(jié)

    在程序開發(fā)過程中,測試是非常重要的一環(huán),甚至有一種開發(fā)模式叫?TDD,先編寫測試,再編寫功能代碼,通過測試來推動(dòng)整個(gè)開發(fā)的進(jìn)行,可見測試在開發(fā)中的重要程度,為此,Go提供了testing框架來方便我們編寫測試,本文將向大家介紹在Go中如何編寫測試代碼
    2023-07-07
  • 使用go語言實(shí)現(xiàn)Redis持久化的示例代碼

    使用go語言實(shí)現(xiàn)Redis持久化的示例代碼

    redis 是一個(gè)內(nèi)存數(shù)據(jù)庫,如果你把進(jìn)程殺掉,那么里面存儲(chǔ)的數(shù)據(jù)都會(huì)消失,那么這篇文章就是來解決 redis 持久化的問題,本文給大家介紹了使用go語言實(shí)現(xiàn)Redis持久化,需要的朋友可以參考下
    2024-07-07
  • go-micro微服務(wù)domain層開發(fā)示例詳解

    go-micro微服務(wù)domain層開發(fā)示例詳解

    這篇文章主要為大家介紹了go-micro微服務(wù)domain層開發(fā)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • go特性之?dāng)?shù)組與切片的問題

    go特性之?dāng)?shù)組與切片的問題

    這篇文章主要介紹了go特性之?dāng)?shù)組與切片的問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Go語言基礎(chǔ)閉包的原理分析示例詳解

    Go語言基礎(chǔ)閉包的原理分析示例詳解

    這篇文章主要為大家介紹了Go語言基礎(chǔ)閉包的底層原理及實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2021-11-11
  • Go語言為什么不支持三元運(yùn)算符原理解析

    Go語言為什么不支持三元運(yùn)算符原理解析

    這篇文章主要為大家介紹了Go語言為什么不支持三元運(yùn)算符原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn)

    Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn)

    Go語言中的sync.RWMutex提供了讀寫鎖機(jī)制,允許多個(gè)協(xié)程并發(fā)讀取共享資源,但在寫操作時(shí)保持獨(dú)占性,本文主要介紹了Golang 并發(fā)讀寫鎖的具體實(shí)現(xiàn),感興趣的可以了解一下
    2025-02-02
  • Go Comparable Type原理深入解析

    Go Comparable Type原理深入解析

    這篇文章主要為大家介紹了Go Comparable Type原理深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • golang中http請(qǐng)求的context傳遞到異步任務(wù)的坑及解決

    golang中http請(qǐng)求的context傳遞到異步任務(wù)的坑及解決

    這篇文章主要介紹了golang中http請(qǐng)求的context傳遞到異步任務(wù)的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03

最新評(píng)論