liveBook · Manning

Unwrap

As explained in Go by Example

Unwrap is a method that exposes the underlying wrapped object or response writer for access to its additional behavior.

Unwrap exposes an underlying wrapped object, especially an http.ResponseWriter, so handlers can recover optional behavior hidden by middleware or embedding. section 9.4.1 section 9.4.3

Use Unwrap to preserve behavior across ResponseWriter wrappers:

  • Implement Unwrap on a wrapper and return its embedded ResponseWriter. section 9.4.3
  • Let handlers or helpers discover Unwrap with a type assertion before accessing the original writer. section 9.8.2
  • Repeat unwrapping through middleware layers until no Unwrap method remains. section 9.8.2
  • Use the recovered writer when optional behavior such as Flush or connection disconnection depends on the original implementation. section 9.4.3 section 9.8.2

Expose the embedded writer

func (ic *Interceptor) Unwrap() http.ResponseWriter { return ic.ResponseWriter } This lets wrapped handlers reach optional interfaces such as http.Flusher. For newer code, http.NewResponseController(w).Flush() can search the wrapper chain and report http.ErrNotSupported when flushing is unavailable. section 9.4.3 section 9.4.2

Listing 9.27 Unwrapping ResponseWriters (link/kit/hio/request.go)
// MaxBytesReader is like [http.MaxBytesReader], but unwraps the
// original [http.ResponseWriter] if it's wrapped.
func MaxBytesReader(
    w http.ResponseWriter, rc io.ReadCloser, max int64,
) io.ReadCloser {
  type unwrapper interface { #1
    Unwrap() http.ResponseWriter  #1
  }  #1
  for { #2
    v, ok := w.(unwrapper) #3
    if !ok {
      break #4
    }
    w = v.Unwrap() #5
  }
  return http.MaxBytesReader(w, rc, max)
}

A recursive MaxBytesReader helper demonstrates how to peel away middleware wrappers before passing the original ResponseWriter to the HTTP server. section 9.8.2

How Go by Example covers it

How deep it goes
Explains implementation, type assertions, recursive unwrapping, and trade-offs before deferring newer lookup to ResponseController.
Examples
Uses Interceptor, streaming with Flush, recursive MaxBytesReader unwrapping, and oversized-request disconnection.
What it assumes
Assumes familiarity with Go interfaces, embedding, type assertions, HTTP handlers, and ResponseWriter wrappers.
What you can do after
Apply it via Go HTTP middleware to preserve optional behavior and restore server handling across nested ResponseWriter wrappers.
How it connects
Connects middleware, ResponseWriter, optional interfaces, Flusher, type assertions, and ResponseController.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Go by Example. The section links point to the parts of the book it draws on.