Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: io: Let MultiWriter return a WriteCloser #28480

Closed
michael-schaller opened this issue Oct 30, 2018 · 4 comments
Closed

proposal: Go 2: io: Let MultiWriter return a WriteCloser #28480

michael-schaller opened this issue Oct 30, 2018 · 4 comments
Labels
FrozenDueToAge Proposal v2 A language change or incompatible library change
Milestone

Comments

@michael-schaller
Copy link
Contributor

The MultiWriter in Go 1 ignores the Close part of WriteClosers. Can this be changed in Go 2 so that the returned writer is a WriteCloser which on Close checks for each given writer if it is a WriteCloser and then calls Close?

This bug is similar to issue #27617 (TeeReader & ReadCloser).

@gopherbot gopherbot added this to the Proposal milestone Oct 30, 2018
@mvdan mvdan added the v2 A language change or incompatible library change label Oct 30, 2018
@ianlancetaylor ianlancetaylor changed the title proposal: io: Let MultiWriter return a WriteCloser in Go 2 proposal: Go 2: io: Let MultiWriter return a WriteCloser Oct 30, 2018
@DeedleFake
Copy link

I've run into this type of problem in several different places before, and I think it's indicative of a more general problem with the interface system. One example that comes to mind is in the implementation of the scripting language I'm working on. There are a number of types that are used to wrap other types to provide extra functionality, such as a Lambda getting wrapped in a Memo to provide automatic memoization. Both the original type and the wrapper implement the same interface, and this interface is used to abstract away which is actually being used, a la subtype polymorphism/dependency injection. The problem is when I want to expose optional extra functionality provided by the inner type. For example, both ScopedFunc and Array implement Func, and Array also implements Lenner. Once I've wrapped an Array, abstracted behind a Func, inside a ScopedFunc, though, the ability to use Lenner's functionality disappears. In other words,

type Func interface { /* ... */ }
type Lenner interface { /* ... */ }

type Array []Func // Implements both Func and Lenner.
type ScopedFunc struct { Inner Func } // Implements Func.

var sf Func = &ScopedFunc{ Inner: Array{} }

// Users of sf have no way to cleanly get access to the Lenner functionality of sf.Inner's actual value.

Maybe this is something that could be solved by generics.

@jimmyfrasche
Copy link
Member

It's fairly easy to wrap MultiWriter to do this.

See: https://play.golang.org/p/fbst3OOSVyk

If you are doing this, you should probably also consider Flush, but that can be handled in a similar manner.

That said, a general rule for helpers like MultiWriter and TeeReader is that, if you're creating them, you're responsible for dealing with the readers/writers they were created from.

@bcmills
Copy link
Contributor

bcmills commented Nov 5, 2018

As noted in #27617 (comment):

Taken to the logical extreme, though, that pattern would either require compile-time metaprogramming or result in an explosion of […] implementations: there are other methods […] that could/should be supported, and for n orthogonal wrappers we currently need 2ⁿ wrappers.¹

¹ See, for example, this experience report.

@ianlancetaylor
Copy link
Contributor

There doesn't seem to be a good reason to change io.MultiWriter. Perhaps we could add io.MultiWriteCloser, which would not have to wait for Go 2. Better still might be to create that outside of the standard library and see whether people choose to use it.

@golang golang locked and limited conversation to collaborators Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge Proposal v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

7 participants