Coroutines and Channels
A coroutine is a lightweight thread that can implement functions or methods to execute in parallel with the main program stream. Use the go keyword: go func(){}. A channel is a direct communication pipeline of coroutines, which is mainly used to transmit data between coroutines, that is, to write data to the channel and read data from the channel.
Declare the channel through the chan keyword, you can declare it using var or :=, or you can declare the channel to be cached. The syntax is as follows:
channelName:= make(chan Type, n)
For example:
dataStream := make(chan string, 1)
Write data to the channel:
dataStream <- "data"
Read data from the channel:
varName := <-dataStream
Close the channel:
close(dataStream)
Go timeout mechanism
Timeout is very important for scenarios where connections to external resources or require limiting execution time. This is because server-side processing that is too long will consume too much resources, resulting in reduced concurrency and even unavailable services.
Use select statements and parallel coroutines to implement timeouts, and the time package must be imported. Then create the channel using the() parameter, and calling (1 * ) will fill the channel after 1 second. The following example implements timeout through channel and select:
package main import ( "fmt" "time" ) func main() { dataChannel:= make(chan string, 1) go func() { (2 * ) dataChannel <- "result 1" }() select { case results := <- dataChannel: (results) case <-(1 * ): ("timeout 1") } }
First, create a cache channel dataChannel, call the function to simulate complex business, and return the result from the non-blocking channel after 2 seconds. The select statement implementation timeout. results := <- dataChannel waits for the result, the (1 * ) statement returns the value after 1 second, so select waits for 1 second first, and after 1 second, it will time out.
The following is to use this mechanism to realize the timeout mechanism for reading files.
Read the entire file
In Go, reading the entire file is generally done using the Read File() function in the ioutil/os package to read the entire file value byte slice. The ioutil package is best not to be used to read large files, as it is completely sufficient for small files.
The os package contains the execution parameter array Args, including all parameters of the execution command, and is an array of string types.
package main import ( "fmt" "io/ioutil" "os" "strconv" "time" ) func main() { filePath := [1] timeOut, _ := ([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: (res) case <-((timeOut) * ): ("Program execution out of time ") } } func ReadFileToString(file string) (string, error) { content, err := (file) // error encountered during reading the data if err != nil { return "", err } // convert bytes to string return string(content), nil }
We can use different timeouts for testing:
go run 1.0 go run 0.9
Read the file by line
You can use the file to read by line, create a Scanner using the (file) constructor, and then read the content line by line through the Scan() and Text() methods. Use the Err() method to check for errors in the process of reading the file.
package main import ( "bufio" "fmt" "log" "os" "strconv" "time" ) func main() { //get filepath and timeout on the terminal filePath := [1] timeOut, _ := ([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 (data) case <-((timeOut) * ): ("Program execution out of time ") break loop case err := <-readerr: if err != nil { (err) } break loop } } } func ReadFileLineByLine(filePath string, data chan string, er chan error) { // open file file, err := (filePath) if err != nil { (err) } // close the file at the end of the program defer () // read the file line by line using scanner scanner := (file) for () { data <- () } close(data) // close causes the range on the channel to break out of the loop er <- () }
Of course, you can also use different timeout times for testing, such as timeout scenarios:
go run 0.1 # Program execution out of time
Read files in block mode
It is very useful for very large files to read blocks, without loading the entire file into memory, and read fixed block size content every time. The following readFileChunk function needs to create a buffer, and read the content of the buffer size every time until an error occurs, indicating that the end of the file has been reached.
Buffer size, target file, and timeout as function parameters, other logic is consistent with the above example:
package main import ( "fmt" "io" "log" "os" "strconv" "time" ) func main() { dataStream := make(chan string, 1) filePath := [1] timeOut, _ := ([2], 64) chunkSize, _ := ([3]) go readFileChunk (filePath, dataStream, int64(chunkSize)) select { case resultData := <- dataStream: (resultData) case <-((timeOut) * ): ("timeout") } } func readFileChunk(filePath string, data chan string, chunkSize int64) { // open file f, err := (filePath) if err != nil { (err) } // remember to close the file at the end of the program defer () buf := make([]byte, chunkSize) for { readTotal, err := (buf) if err != nil && err != { (err) } if err == { break } data <- string(buf[:readTotal]) } close(data) }
Summarize
The Golang timeout mechanism is necessary when a resource-intensive program is being executed, which helps terminate such a lengthy program. This article shows the implementation of timeout mechanisms for reading files in different ways through examples.
This is the article about this example of how Golang implements the timeout mechanism to read files. For more related Golang timeout mechanism to read files, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!