登录
首页 >  Golang >  Go问答

如何在 golang 中显式发送 EOF 到 io.ReadCloser?

来源:stackoverflow

时间:2024-04-02 12:21:36 354浏览 收藏

最近发现不少小伙伴都对Golang很感兴趣,所以今天继续给大家介绍Golang相关的知识,本文《如何在 golang 中显式发送 EOF 到 io.ReadCloser?》主要内容涉及到等等知识点,希望能帮到你!当然如果阅读本文时存在不同想法,可以在评论中表达,但是请勿使用过激的措辞~

问题内容

希望您身体健康地收到此消息。

所以我正在研究的 golang 程序中存在这个错误,代码库中的 stdcopy.stdcopy() 阻塞方法可能会导致所有内容挂起。出现此问题的原因是 docker 不断向 stdcopy 阻塞方法发送信息,而阻塞方法只有在向其发送 eof 时才能停止运行。 stdcopy 接受 readcloser 类型参数,这是阻塞方法从 docker 读取信息的方式。 goroutine 也会在程序进入阻塞方法之前使用。换句话说,stdcopy 阻塞方法在新线程中运行,而主线程与其并行运行。但是,阻塞方法现在会阻塞新线程,这并不能解决问题。

我试图防止这个问题的方法是在主线程中显式关闭这个 readcloser,然后向持有 stdcopy 阻塞方法的新线程发送一个 eof,以通过超时错误强制停止它。这应该会阻止整个程序挂起,因为阻塞方法是它挂起的原因。我通过存储我打开的每个 readcloser 的映射来做到这一点,然后以特定方法手动关闭它们,该方法旨在在我们的程序停止时运行。我不确定关闭 readcloser 接口是否会自动发送 eof(我检查了 golang 文档,但找不到任何相关信息:https://golang.org/pkg/io/#readcloser)。

我决定明确地向 readcloser 发送一个 eof,以防万一。然而,我该怎么做呢?我正在考虑利用我对通道的了解,并通过通道将 io.eof 传递到正在运行阻塞方法的 go 例程中。但是,io.readcloser 不是通道类型,所以我不能这样做。

关闭 io.readcloser 是否会自动发送 eof?如果不是,如何将 eof 发送到 io.readcloser 以便阻止方法停止运行?

如果我的解释中有任何不合理的地方并且您希望我澄清,请告诉我。由于我对 golang 比较陌生,所以如果您认为我有错误,请随时纠正我。

非常感谢您抽出宝贵的时间,如有任何想法,请告诉我!

-----编辑-----

以下是我迄今为止编写的一些代码,以便更好地理解:

//Closing all of the ReadClosers opened to prevent blocking
        for k := range streamer.inputReadClosers {
            (*k).Close()
            //(*k) <- io.EOF //does not work since io.ReadCloser is not of channel type
        }

因此,对于某些上下文,streamer 只是一个包含属性调用 inputreadclosers 的结构,它是所有打开的 readclosers 的指针映射。然后,我显式关闭 readclosers,然后目标是手动将 eof 发送到该 readcloser。

有关 readcloser 如何初始化的一些信息:

所以我有一个文件,其中有一个方法具有以下方法头 func (streamer *logstreamer) startstreamingfromdockerlogs(input io.readcloser) error。当我检查其他文件中使用 startstreamingfromdockerlogs(...) 的实例时,我发现传递了一个 readcloser 变量,并且 readcloser 变量按以下方式初始化: readcloser, err := dockermanager.getcontainerlogs(.. ...这里三个参数.....)


正确答案


这实际上是一条评论,而不是一个答案,只是它太大而无法成为评论(并且需要一些格式)。

这里存在一些根本性的不匹配,使得这个问题无法解决,如上所述:

  • 首先,文件结束符(例如由 io.eof 错误表示)不能通过任何类型的数据流发送。这是一个适用于流的条件,在该条件下无法接收更多数据(至少目前如此,该条件将来可能会消失)。

  • 其次,io.readcloser 就是实现 readclos​​e 方法的任何东西(具有 io.readerio.closer)。您不能将 eof“发送”到此。当其 read 函数返回 io.eof 错误作为其两个返回值之一时,就会发生 eof。如果某个类型t实现了io.readcloser,并且您将t类型的值传递给某个函数f,并且f em> 调用其 read 方法,并返回 io.eof 作为其错误条件,然后此 t 的读取器已生成 eof 条件。

Penelope Stevens said in a comment 所示,如果我们知道恰好实现 io.readcloser 的实际具体类型 tc那么我们也许能够找到某种方法说服 tc 的阅读器返回 io.eof 错误。这反过来又需要检查tc的源代码或文档。例如:

type Foo struct {
    // unexported fields
    TemporaryEOF bool
}
...
func (Foo *f) Read(p []byte) (n int, err error) {
    // if we're supposed to assert a temporary EOF now, do so
    if f->temporaryEOF {
        return 0, io.EOF
    }
    // rest of code here
}
// implement io.Closer() here too

这告诉我们,foo 对象实际上实现了 io.readcloser,只需将其 temporaryeof 数据字段设置为 true 即可强制在一段时间内显示 eof。

这不适用于实现 io.readcloser 的其他项目,因为它们没有 temporaryeof 数据字段。这种在程序运行期间强制 eof 一段时间的特殊方法是 foo 对象所特有的。 这正是我们无法解决的问题,因为我们没有正确的信息:导致 eof 条件发生的代码是 read 函数中 tc 的代码除非您向我们展示该代码(或者允许我们找到该代码的东西),否则我们无法告诉您如何使其产生 eof 条件。

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>