3

I'm teaching myself to use the net/http package using The Way to Go book. He mentions a way to wrap handling functions in a closure that takes care of panics like so:

func Index(w http.ResponseWriter, req *http.Request) {
    w.Header().Set("Content-Type", "text/html")
    fmt.Fprint(w, "<h2>Index</h2>")
}

func logPanics(function HandleFunc) HandleFunc {
    return func(w http.ResponseWriter, req *http.Request) {
        defer func() {
            if err := recover(); err != nil {
              log.Printf("[%v] caught panic: %v", req.RemoteAddr, err)
            }
        }()
        function(w, req)
    }
}

And then call http.HandleFunc using the above like so:

http.HandleFunc("/", logPanics(Index))

What I want to do is to "stack" more than one function to include more functionality. I wanted to add a closure that adds a mime type via .Header().Set(...) and I can call it like this:

func addHeader(function HandleFunc) HandleFunc {
    return func(w http.ResponseWriter, req *http.Request) {
        w.Header().Set("Content-Type", "text/html")
        function(w, req)
    }
}
(then in main())
http.HandleFunc("/", logPanics(addHeader(Index)))

But I thought it would be nice to shorten that whilst still keeping these functions separate using a wrapper function:

func HandleWrapper(function HandleFunc) HandleFunc {
    return func(w http.ResponseWriter, req *http.Request) {
        logPanics(addHeader(function(w, req)))
    }
}

But I get a function(w, req) used as value error. I haven't worked much with closures before and I feel like I'm definitely missing something here.

Thanks for the help!

1 Answer 1

2

function(w, req) is a function call without a return value, while addHeader expects a function as its argument.

If you want to combine the two wrapper functions, you probably want something like this:

func HandleWrapper(function HandleFunc) HandleFunc {
    return logPanics(addHeader(function))
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! That was it. As I understand it, the wrapper functions return function objects without executing the code - all the code gets executed when the function is actually called, right?
Yep. So it isn't necessary to intercept the actual calls to the HandlerFunc in order to compose two wrappers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.