我的函数是否应该以通道为输入?

huangapple go评论75阅读模式
英文:

Should my function take channels as input?

问题

我正在构建一个管理和写入数据到文件的Go库。我已经编写了一个文件写入器,可以将数据传递给它,然后它会通过缓冲写入器将数据写入文件。这意味着使用该库的服务在关闭时必须调用一个关闭方法,以便将缓冲区中的任何数据写入文件。我看到两种处理方式:
1)公开一个Close方法供服务使用。
2)使用通道。如果服务关闭通道,那么它将关闭库中的缓冲区。我的库函数看起来像这样:

func (r *Repo) Write(ctx context.Context, data <-chan Data, errCh chan<- error) error {
	for doc := range data {
		err := r.file.Write(ctx, doc)
		if err != nil {
			errCh <- err
		}
	}

	err = r.file.Close(ctx)
	return err
}

我的问题是,Write()的签名是否合理,因为它接受一个接收通道和一个用于错误的发送通道作为输入?我还没有看到类似的例子。也许有更好的组织方式?

英文:

I'm building a go library that manages and writes data to a file. I have written a file writer that I can pass data to, and it'll write that data to the file via a buffered writer. This means that a service using the library will have to call a close method once the service shuts down to write anything still in the buffer. I see two ways of handling this:

  1. Expose a Close method that the service can use.
  2. Use channels. If the service closes the channel, that'll close the buffer in the library. My lib function would look like this:
func (r *Repo) Write(ctx context.Context, data &lt;-chan Data, errCh chan&lt;- error) error {
	for doc := range data {
		err := r.file.Write(ctx, doc)
		if err != nil {
			errCh &lt;- err
		}
	}

	err = r.file.Close(ctx)
	return err
}

My question is if the Write() signature make sense, as it takes a receive channel and a send channel for errors as input? I haven't seen similar examples of this. Maybe there is a better way of organising this?

答案1

得分: 0

选项1,即使用Close函数更有意义,特别是如果看一下Go语言的做法。

此外,使用通道会使事情变得复杂,当可以在没有它们的情况下完成任务时。
就像Write函数的实现中有一个for循环,不断读取数据。

    for doc := range data {
        err := r.file.Write(ctx, doc)
        if err != nil {
            errCh &lt;- err
        }
    }

这意味着调用此写函数的任何人都会被阻塞,如果需要非阻塞行为,则需要将其放入goroutine中调用。

此外,具有简单的写入签名,如:
func (r *Repo) Write(data Data) error
看起来更清晰,如果上下文在每次调用函数时不会更改,可以将其作为Repo初始化的一部分。

英文:

Option 1. i.e. using Close function makes more sense especially if one looks at the go way of doing things.

Also using channels complicates things when things can be done without them.
Like the Write implementation has a for loop which keeps on reading data.

    for doc := range data {
        err := r.file.Write(ctx, doc)
        if err != nil {
            errCh &lt;- err
        }
    }

this means any one calling this write function would get blocked and will need to call this into a goroutine if non-blocking behaviour is required.

Additionally having a simple write signature like:
func (r *Repo) Write(data Data) error
looks more clean, and the context can be made a part of Repo initialisation if that's not changing each time function is getting called.

huangapple
  • 本文由 发表于 2021年11月17日 00:09:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/69992522.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定