FAQ
I had an exported method which returned a *tar.Reader, but due to some
underlying changes, I needed the caller of that method to "close" the tar
file when through with the returned *tar.Reader. However, *tar.Reader does
not have a Close method.

So I changed my method, which used to return *tar.Reader, to return
TarReadCloser, a new type in my package, defined thus:

// A TarReadCloser is a tar.Reader which also implements Close.
type TarReadCloser struct {
*tar.Reader
io.Closer
}

The implementation of my method used to say something like this:

return tar.NewReader(r)

and now it does this:

return &TarReadCloser{Reader: tar.NewReader(r), Closer: r}

This is a striking elegance; far better than what you have to do without
the wonders of anonymous fields and method promotion. For example, without
method promotion, I'd need to define methods on TarReadCloser,
corresponding to all the methods of *tar.Reader, and then I'd need to keep
that up-to-date with any changes to the archive/tar package. Instead, the
compiler will do that for me through this relatively simple expedient.

Thomas

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Dave Cheney at Mar 1, 2013 at 11:18 pm
    I love using interfaces to filter methods embedded into other types. I've used (or possibly overused) this is the ssh pkg with great personal satisfaction.

    Dave
    On 02/03/2013, at 8:21, "Thomas Bushnell, BSG" wrote:

    I had an exported method which returned a *tar.Reader, but due to some underlying changes, I needed the caller of that method to "close" the tar file when through with the returned *tar.Reader. However, *tar.Reader does not have a Close method.

    So I changed my method, which used to return *tar.Reader, to return TarReadCloser, a new type in my package, defined thus:

    // A TarReadCloser is a tar.Reader which also implements Close.
    type TarReadCloser struct {
    *tar.Reader
    io.Closer
    }

    The implementation of my method used to say something like this:

    return tar.NewReader(r)

    and now it does this:

    return &TarReadCloser{Reader: tar.NewReader(r), Closer: r}

    This is a striking elegance; far better than what you have to do without the wonders of anonymous fields and method promotion. For example, without method promotion, I'd need to define methods on TarReadCloser, corresponding to all the methods of *tar.Reader, and then I'd need to keep that up-to-date with any changes to the archive/tar package. Instead, the compiler will do that for me through this relatively simple expedient.

    Thomas

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Nate Finch at Mar 2, 2013 at 12:04 am
    IMO interfaces are the best part of Go, by far.
    On Friday, March 1, 2013 6:18:37 PM UTC-5, Dave Cheney wrote:

    I love using interfaces to filter methods embedded into other types. I've
    used (or possibly overused) this is the ssh pkg with great personal
    satisfaction.

    Dave

    On 02/03/2013, at 8:21, "Thomas Bushnell, BSG" wrote:

    I had an exported method which returned a *tar.Reader, but due to some
    underlying changes, I needed the caller of that method to "close" the tar
    file when through with the returned *tar.Reader. However, *tar.Reader does
    not have a Close method.

    So I changed my method, which used to return *tar.Reader, to return
    TarReadCloser, a new type in my package, defined thus:

    // A TarReadCloser is a tar.Reader which also implements Close.
    type TarReadCloser struct {
    *tar.Reader
    io.Closer
    }

    The implementation of my method used to say something like this:

    return tar.NewReader(r)

    and now it does this:

    return &TarReadCloser{Reader: tar.NewReader(r), Closer: r}

    This is a striking elegance; far better than what you have to do without
    the wonders of anonymous fields and method promotion. For example, without
    method promotion, I'd need to define methods on TarReadCloser,
    corresponding to all the methods of *tar.Reader, and then I'd need to keep
    that up-to-date with any changes to the archive/tar package. Instead, the
    compiler will do that for me through this relatively simple expedient.

    Thomas

    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/groups/opt_out.


    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Tim Harig at Mar 2, 2013 at 12:30 am

    On Fri, Mar 01, 2013 at 04:04:17PM -0800, Nate Finch wrote:
    IMO interfaces are the best part of Go, by far.
    Agreed, interfaces are the reason that I use Go.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jiahua Chen at Mar 3, 2013 at 5:14 am

    hello Thomas,
    I'm working on archive/tar pkg, but when the .tar has a directoey in it,
    every time it returns me a "invalid tar header", is there a way to know
    if it's directory?
    Thanks!
    >

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Thomas Bushnell, BSG at Mar 3, 2013 at 5:25 am
    Next returns a Header, which contains the type in .Typeflag.

    But if you get ErrHeader, I suspect something may be amiss in the archive
    itself.

    On Sat, Mar 2, 2013 at 5:43 PM, Jiahua Chen wrote:

    hello Thomas,
    I'm working on archive/tar pkg, but when the .tar has a directoey in it,
    every time it returns me a "invalid tar header", is there a way to know
    if it's directory? Thanks!
    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Blake Smith at Mar 3, 2013 at 6:21 pm
    Thanks Thomas, until your post I had no idea this Golang feature even
    existed. I was able to cleanup a spot in my code that was doing something
    very similar (A Reader that wraps a ReadCloser). The old code was breaking
    encapsulation by returning the Reader and the ReadCloser and relying on the
    caller to use the Reader and then call Close() directly on the ReadCloser.

    Very simplifed old code:

    func getReader() (io.Reader, io.ReadCloser, error) {
    readCloser := NewReadCloser()
    reader := NewReader(readCloser)

    // Must return reader along with readCloser so the caller can close the
    underlying stream once it's done reading
    return reader, readCloser, nil
    }

    Simplified new code:

    func getReader() (*MyReadCloser, error) {
    readCloser := NewReadCloser()
    mrc := &MyReadCloser{Reader: NewReader(readCloser), Closer: readCloser}

    // Caller can call Read() as well as Close() directly on MyReadCloser -
    no breaking encapsulation and simple - Victory!
    return mrc, nil
    }

    Does this Go feature have a common name? It looks like "interface
    composition" but is there a more accurate term for it?

    Thanks again!

    Blake

    On Friday, March 1, 2013 3:21:52 PM UTC-6, Thomas Bushnell, BSG wrote:

    I had an exported method which returned a *tar.Reader, but due to some
    underlying changes, I needed the caller of that method to "close" the tar
    file when through with the returned *tar.Reader. However, *tar.Reader does
    not have a Close method.

    So I changed my method, which used to return *tar.Reader, to return
    TarReadCloser, a new type in my package, defined thus:

    // A TarReadCloser is a tar.Reader which also implements Close.
    type TarReadCloser struct {
    *tar.Reader
    io.Closer
    }

    The implementation of my method used to say something like this:

    return tar.NewReader(r)

    and now it does this:

    return &TarReadCloser{Reader: tar.NewReader(r), Closer: r}

    This is a striking elegance; far better than what you have to do without
    the wonders of anonymous fields and method promotion. For example, without
    method promotion, I'd need to define methods on TarReadCloser,
    corresponding to all the methods of *tar.Reader, and then I'd need to keep
    that up-to-date with any changes to the archive/tar package. Instead, the
    compiler will do that for me through this relatively simple expedient.

    Thomas
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMar 1, '13 at 9:21p
activeMar 3, '13 at 6:21p
posts7
users6
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase