patterngoMinor
Strip a newline and add more text to a Go bytes.Buffer
Viewed 0 times
buffernewlinetextmorebytesandstripadd
Problem
I wrote a little timer middleware to append the request duration to the end of the log message returned by the excellent Gorilla Toolkit's
That handler accepts an
The following code works, but I am not sure that I made the best use of the Go
Is there a better way to write this in Go?
CombinedLoggingHandler from the handlers package.That handler accepts an
io.Writer and an http.Handler, and fills the Writer with a newline-terminate string containing the Apache Combined Format log entry for the current server request. I would like to remove the trailing newline and add " completed in xxx", where xxx is the amount of time the request took.The following code works, but I am not sure that I made the best use of the Go
bytes.Buffer in the way I stripped the newline:func timerHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
var b bytes.Buffer
hand := handlers.CombinedLoggingHandler(&b, h)
defer func(start time.Time) {
prefix := bytes.TrimRight(b.Bytes(), "\n")
os.Stdout.Write(prefix)
fmt.Printf(" completed in %v\n", time.Since(start))
}(time.Now())
hand.ServeHTTP(res, req)
})
}Is there a better way to write this in Go?
Solution
I believe you are over-complicating the handler function by introducing the deferred function with the start time closure. Additionally, you are performing 2 writes to accomplish the logging, when one would be better.
So, Why have the "defer"? This code:
would be simpler to understand as:
Then, in addition, I would manipulate the bytes to trim and add the completion message, and then output them...., so I would change the last part of the code to be something like:
That still irks me a bit, because i don't like the
So, Why have the "defer"? This code:
var b bytes.Buffer
hand := handlers.CombinedLoggingHandler(&b, h)
defer func(start time.Time) {
prefix := bytes.TrimRight(b.Bytes(), "\n")
os.Stdout.Write(prefix)
fmt.Printf(" completed in %v\n", time.Since(start))
}(time.Now())
hand.ServeHTTP(res, req)would be simpler to understand as:
start := time.Now()
var b bytes.Buffer
hand := handlers.CombinedLoggingHandler(&b, h)
hand.ServeHTTP(res, req)
prefix := bytes.TrimRight(b.Bytes(), "\n")
os.Stdout.Write(prefix)
fmt.Printf(" completed in %v\n", time.Since(start))Then, in addition, I would manipulate the bytes to trim and add the completion message, and then output them...., so I would change the last part of the code to be something like:
msg := bytes.TrimRight(b.Bytes(), "\n")
msg := append(msg, []byte(fmt.Sprintf(" completed in %v\n", time.Since(start)...)
os.Stdout.Write(msg)That still irks me a bit, because i don't like the
os.Stdout.Write being a constant value in there.... I would make that a parameter somehow, or a constant of some sort....var logDest io.Writer = os.StdoutCode Snippets
var b bytes.Buffer
hand := handlers.CombinedLoggingHandler(&b, h)
defer func(start time.Time) {
prefix := bytes.TrimRight(b.Bytes(), "\n")
os.Stdout.Write(prefix)
fmt.Printf(" completed in %v\n", time.Since(start))
}(time.Now())
hand.ServeHTTP(res, req)start := time.Now()
var b bytes.Buffer
hand := handlers.CombinedLoggingHandler(&b, h)
hand.ServeHTTP(res, req)
prefix := bytes.TrimRight(b.Bytes(), "\n")
os.Stdout.Write(prefix)
fmt.Printf(" completed in %v\n", time.Since(start))msg := bytes.TrimRight(b.Bytes(), "\n")
msg := append(msg, []byte(fmt.Sprintf(" completed in %v\n", time.Since(start)...)
os.Stdout.Write(msg)var logDest io.Writer = os.StdoutContext
StackExchange Code Review Q#150601, answer score: 4
Revisions (0)
No revisions yet.