FAQ
I'm wrapping a http.ResponseWriter to track bandwidth use and peek at
headers before they're sent. There's a helper function http.ServeContent
that makes use of several extra optional methods on response writers, such
as Flush, and via io.CopyN, ReaderFrom. For performance and transparency
reasons it's desirable that my wrapper offer these functions when type
assertions check for them. But their supposed existence depends on whether
the wrapped response writer implements them. By using anonymous fields,
it's possible to mix and optionally override the methods those fields types
provide. However type assertions don't also pass through to the embedded
fields. Here's an example: http://play.golang.org/p/t9AZNb1MiG. In the
example, Eminem is stored as a poser, but he's actually the Real Slim
Shady. But attempts to type assert him so don't work.

What are my options here? If my wrapper purports to implement methods that
its embedded types *may* implement, I risk changing the behaviour of
callers, and having to implement work arounds when the embedded types don't
actually support something.

For a concrete example:

type wrapper struct {
   http.ResponseWriter
}

func (me wrapper) ReadFrom(src io.Reader) (int64, error) {
   if rf, ok := me.ResponseWriter.(io.ReaderFrom); ok {
     return rf.ReadFrom(src)
   }
   // ????
   return io.Copy(me.ResponseWriter, src)
}


--
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/d/optout.

Search Discussions

  • Chris Hines at Mar 8, 2015 at 2:31 am

    On Saturday, March 7, 2015 at 9:03:04 PM UTC-5, Matt Joiner wrote:
    I'm wrapping a http.ResponseWriter to track bandwidth use and peek at
    headers before they're sent. There's a helper function http.ServeContent
    that makes use of several extra optional methods on response writers, such
    as Flush, and via io.CopyN, ReaderFrom. For performance and transparency
    reasons it's desirable that my wrapper offer these functions when type
    assertions check for them. But their supposed existence depends on whether
    the wrapped response writer implements them. By using anonymous fields,
    it's possible to mix and optionally override the methods those fields types
    provide. However type assertions don't also pass through to the embedded
    fields. Here's an example: http://play.golang.org/p/t9AZNb1MiG. In the
    example, Eminem is stored as a poser, but he's actually the Real Slim
    Shady. But attempts to type assert him so don't work.

    What are my options here? If my wrapper purports to implement methods that
    its embedded types *may* implement, I risk changing the behaviour of
    callers, and having to implement work arounds when the embedded types don't
    actually support something.

    For a concrete example:

    type wrapper struct {
    http.ResponseWriter
    }

    func (me wrapper) ReadFrom(src io.Reader) (int64, error) {
    if rf, ok := me.ResponseWriter.(io.ReaderFrom); ok {
    return rf.ReadFrom(src)
    }
    // ????
    return io.Copy(me.ResponseWriter, src)
    }
    I haven't totally groked what you are trying to do, so forgive me if this
    doesn't help.

    Does it help that this http://play.golang.org/p/z1nqvV1jhv, or this
    http://play.golang.org/p/mi5nxAdXMi work?

    Your example hides the real value behind two levels of interface values.
    One where it is embedded in the eminem struct and the other where it is
    assigned to the realShady variable of type poser. As a result you need to
    perform two type assertions to dig it back out, or replace one of the
    interface values with a non-interface value.

    Chris

    --
    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/d/optout.
  • Matt Joiner at Mar 8, 2015 at 3:16 am
    Thanks for looking. Unfortunately neither help, since the user of my
    wrapper won't be asserting for, and doesn't care for the type of the
    wrapper. It's intended to be transparent, which is why it implements
    ResponseWriter in the first place.
    On 8 March 2015 at 13:31, Chris Hines wrote:
    On Saturday, March 7, 2015 at 9:03:04 PM UTC-5, Matt Joiner wrote:

    I'm wrapping a http.ResponseWriter to track bandwidth use and peek at
    headers before they're sent. There's a helper function http.ServeContent
    that makes use of several extra optional methods on response writers, such
    as Flush, and via io.CopyN, ReaderFrom. For performance and transparency
    reasons it's desirable that my wrapper offer these functions when type
    assertions check for them. But their supposed existence depends on whether
    the wrapped response writer implements them. By using anonymous fields,
    it's possible to mix and optionally override the methods those fields types
    provide. However type assertions don't also pass through to the embedded
    fields. Here's an example: http://play.golang.org/p/t9AZNb1MiG. In the
    example, Eminem is stored as a poser, but he's actually the Real Slim
    Shady. But attempts to type assert him so don't work.

    What are my options here? If my wrapper purports to implement methods
    that its embedded types *may* implement, I risk changing the behaviour of
    callers, and having to implement work arounds when the embedded types don't
    actually support something.

    For a concrete example:

    type wrapper struct {
    http.ResponseWriter
    }

    func (me wrapper) ReadFrom(src io.Reader) (int64, error) {
    if rf, ok := me.ResponseWriter.(io.ReaderFrom); ok {
    return rf.ReadFrom(src)
    }
    // ????
    return io.Copy(me.ResponseWriter, src)
    }
    I haven't totally groked what you are trying to do, so forgive me if this
    doesn't help.

    Does it help that this http://play.golang.org/p/z1nqvV1jhv, or this
    http://play.golang.org/p/mi5nxAdXMi work?

    Your example hides the real value behind two levels of interface values.
    One where it is embedded in the eminem struct and the other where it is
    assigned to the realShady variable of type poser. As a result you need to
    perform two type assertions to dig it back out, or replace one of the
    interface values with a non-interface value.

    Chris

    --
    You received this message because you are subscribed to a topic in the
    Google Groups "golang-nuts" group.
    To unsubscribe from this topic, visit
    https://groups.google.com/d/topic/golang-nuts/HKY3mI7Q2jY/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to
    golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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/d/optout.
  • Speter at Mar 8, 2015 at 3:53 am
    If you only care about few extra methods (2-3), you can create (generate)
    wrappers for all combinations of them (2^n wrapper types in the worst case)
    and return the appropriate type based on the instance to be wrapped, but
    I'm guessing that's exactly what you're trying to avoid.

    For a general solution reflect.MakeInterface could help but it's not
    implemented ( https://golang.org/issue/4146 ). That could allow proxying
    any and all methods, so consumers asserting for any interface could keep
    working. (Asserting for concrete types still wouldn't work and I don't see
    any way for making that work transparently in general.)

    Peter

    On Sun, Mar 8, 2015 at 12:16 PM, Matt Joiner wrote:

    Thanks for looking. Unfortunately neither help, since the user of my
    wrapper won't be asserting for, and doesn't care for the type of the
    wrapper. It's intended to be transparent, which is why it implements
    ResponseWriter in the first place.
    On 8 March 2015 at 13:31, Chris Hines wrote:
    On Saturday, March 7, 2015 at 9:03:04 PM UTC-5, Matt Joiner wrote:

    I'm wrapping a http.ResponseWriter to track bandwidth use and peek at
    headers before they're sent. There's a helper function http.ServeContent
    that makes use of several extra optional methods on response writers, such
    as Flush, and via io.CopyN, ReaderFrom. For performance and transparency
    reasons it's desirable that my wrapper offer these functions when type
    assertions check for them. But their supposed existence depends on whether
    the wrapped response writer implements them. By using anonymous fields,
    it's possible to mix and optionally override the methods those fields types
    provide. However type assertions don't also pass through to the embedded
    fields. Here's an example: http://play.golang.org/p/t9AZNb1MiG. In the
    example, Eminem is stored as a poser, but he's actually the Real Slim
    Shady. But attempts to type assert him so don't work.

    What are my options here? If my wrapper purports to implement methods
    that its embedded types *may* implement, I risk changing the behaviour of
    callers, and having to implement work arounds when the embedded types don't
    actually support something.

    For a concrete example:

    type wrapper struct {
    http.ResponseWriter
    }

    func (me wrapper) ReadFrom(src io.Reader) (int64, error) {
    if rf, ok := me.ResponseWriter.(io.ReaderFrom); ok {
    return rf.ReadFrom(src)
    }
    // ????
    return io.Copy(me.ResponseWriter, src)
    }
    I haven't totally groked what you are trying to do, so forgive me if this
    doesn't help.

    Does it help that this http://play.golang.org/p/z1nqvV1jhv, or this
    http://play.golang.org/p/mi5nxAdXMi work?

    Your example hides the real value behind two levels of interface values.
    One where it is embedded in the eminem struct and the other where it is
    assigned to the realShady variable of type poser. As a result you need to
    perform two type assertions to dig it back out, or replace one of the
    interface values with a non-interface value.

    Chris

    --
    You received this message because you are subscribed to a topic in the
    Google Groups "golang-nuts" group.
    To unsubscribe from this topic, visit
    https://groups.google.com/d/topic/golang-nuts/HKY3mI7Q2jY/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to
    golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
    --
    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/d/optout.
    --
    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/d/optout.
  • Matt Joiner at Mar 8, 2015 at 4:19 am
    Thanks, this comment precisely describes my
    problem: https://github.com/golang/go/issues/4146#issuecomment-66070605
    On Sunday, 8 March 2015 14:53:08 UTC+11, speter wrote:

    If you only care about few extra methods (2-3), you can create (generate)
    wrappers for all combinations of them (2^n wrapper types in the worst case)
    and return the appropriate type based on the instance to be wrapped, but
    I'm guessing that's exactly what you're trying to avoid.

    For a general solution reflect.MakeInterface could help but it's not
    implemented ( https://golang.org/issue/4146 ). That could allow proxying
    any and all methods, so consumers asserting for any interface could keep
    working. (Asserting for concrete types still wouldn't work and I don't see
    any way for making that work transparently in general.)

    Peter


    On Sun, Mar 8, 2015 at 12:16 PM, Matt Joiner <anac...@gmail.com
    <javascript:>> wrote:
    Thanks for looking. Unfortunately neither help, since the user of my
    wrapper won't be asserting for, and doesn't care for the type of the
    wrapper. It's intended to be transparent, which is why it implements
    ResponseWriter in the first place.

    On 8 March 2015 at 13:31, Chris Hines <ggr...@cs-guy.com <javascript:>>
    wrote:
    On Saturday, March 7, 2015 at 9:03:04 PM UTC-5, Matt Joiner wrote:

    I'm wrapping a http.ResponseWriter to track bandwidth use and peek at
    headers before they're sent. There's a helper function http.ServeContent
    that makes use of several extra optional methods on response writers, such
    as Flush, and via io.CopyN, ReaderFrom. For performance and transparency
    reasons it's desirable that my wrapper offer these functions when type
    assertions check for them. But their supposed existence depends on whether
    the wrapped response writer implements them. By using anonymous fields,
    it's possible to mix and optionally override the methods those fields types
    provide. However type assertions don't also pass through to the embedded
    fields. Here's an example: http://play.golang.org/p/t9AZNb1MiG. In the
    example, Eminem is stored as a poser, but he's actually the Real Slim
    Shady. But attempts to type assert him so don't work.

    What are my options here? If my wrapper purports to implement methods
    that its embedded types *may* implement, I risk changing the behaviour of
    callers, and having to implement work arounds when the embedded types don't
    actually support something.

    For a concrete example:

    type wrapper struct {
    http.ResponseWriter
    }

    func (me wrapper) ReadFrom(src io.Reader) (int64, error) {
    if rf, ok := me.ResponseWriter.(io.ReaderFrom); ok {
    return rf.ReadFrom(src)
    }
    // ????
    return io.Copy(me.ResponseWriter, src)
    }
    I haven't totally groked what you are trying to do, so forgive me if
    this doesn't help.

    Does it help that this http://play.golang.org/p/z1nqvV1jhv, or this
    http://play.golang.org/p/mi5nxAdXMi work?

    Your example hides the real value behind two levels of interface values.
    One where it is embedded in the eminem struct and the other where it is
    assigned to the realShady variable of type poser. As a result you need to
    perform two type assertions to dig it back out, or replace one of the
    interface values with a non-interface value.

    Chris

    --
    You received this message because you are subscribed to a topic in the
    Google Groups "golang-nuts" group.
    To unsubscribe from this topic, visit
    https://groups.google.com/d/topic/golang-nuts/HKY3mI7Q2jY/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to
    golang-nuts...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/d/optout.
    --
    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/d/optout.
    --
    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/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMar 8, '15 at 2:03a
activeMar 8, '15 at 4:19a
posts5
users3
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase