为什么在for循环中调用ioutil.ReadFile()后会挂起?

时间:2019-03-26 05:34:42

标签: image file go io

我编写了一个将图像转换为base64字符串的函数:

func getBase64Screenshot() string {
    // Image name
    imageName := "Screenshots/screenshot.png"

    imageFileBytes, err := ioutil.ReadFile(imageName)
    handleError(err)

    // Converts file to base64 string
    encoded := base64.StdEncoding.EncodeToString(imageFileBytes)

    return encoded
}

上面的函数在for loop中被调用,但是在for循环的一些迭代之后,该程序只是挂在行imageFileBytes, err := ioutil.ReadFile(imageName)上(它不会引发错误,它只是停止运行和档位。

我进行了一些实验,发现如果使用较小的图像,它将在停顿之前经过for loop的约5次迭代,但是如果我截屏整个屏幕,则只能通过第一个for loop在停顿之前的迭代。

我的问题是:是什么导致程序挂起,我能做些什么来防止其挂起?

谢谢!

3 个答案:

答案 0 :(得分:2)

调试代码。


尝试一下,让我知道这是否也适合您:
在Linux上,这对我来说就像一个魅力:

package main

import (
    "encoding/base64"
    "fmt"
    "io/ioutil"
    "log"
    "os"
)

func main() {
    for i := 0; i < 10; i++ {
        fmt.Println(getBase64Screenshot()[:10])
    }
}
func getBase64Screenshot() string {
    buf, err := ioutil.ReadFile(os.Args[0])
    if err != nil {
        log.Fatal(err)
    }
    encoded := base64.StdEncoding.EncodeToString(buf)
    return encoded
}

输出:

time go run main.go
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ
f0VMRgIBAQ

real    0m0.340s
user    0m0.369s
sys     0m0.128s

答案 1 :(得分:2)

一种调试问题的方法是将SIGABRT发送到正在运行的程序(挂起时)以发送到causes the program to exit with a stack dump

kill -ABRT <pid>
# or CTRL+Pause on Windows.

然后,您将看到程序挂起的位置,以及该程序实际上是否与您的功能相关。

答案 2 :(得分:0)

嘿,我能够解决这个问题。

您看到,最初,我在上面编写的函数getBase64Screenshot()goroutine内部每10秒被调用一次。

为解决此问题,我重构了代码以消除goroutine,而是在无限循环内调用getBase64Screenshot()

for {
        getBase64Screenshot()
        time.Sleep(timedelayMilliseconds * time.Millisecond)
    }

我已经通过运行30分钟以上的超大屏幕截图(> 1MB大小)测试了上述代码,并且从未崩溃或停止

尽管我已经解决了遇到的问题,但我仍然无法弄清楚到底是什么原因造成的。我欢迎任何关于为什么我上面的原始代码停滞不前的理论。