Passing http.ResponseWriter by value or reference? - go

Assume I'm having a central method which adds a specific header to the http.ResponseWriter. I don't want to use a HandleFunc wrapper.
I wonder, whether I'd send in the ResponseWriter by reference. So, what would be correct:
addHeaders(&w)
or
addHeaders(w)
Asked differently:
func addHeaders(w *http.ResponseWriter) {...}
or
func addHeaders(w http.ResponseWriter) {...}
From my understanding, I'd say the first version would be correct, as I don't want to create a copy of ResponseWriter. But I haven't seen any code where ResponseWriter is passed by reference and wonder why.
Thanks!

http.ResponseWriter is an interface. You want to pass its value, since it internally contains a pointer to the actual Writer. You almost never want a pointer to an interface.
Look at what a standard handler func's signature is:
func(http.ResponseWriter, *http.Request)
Notice that ResponseWriter isn't a pointer.

Related

How to convert multipart.File to io.Reader

Maybe I'm just not understanding how to use the Read method for the File object, but I see in docs that io.Reader is within the multipart.File interface, but I don't understand how to access it. Any guidance would be greatly appreciated.
That means that the multipart.File interface includes the io.Reader interface, so any object that is a valid multipart.File is also a valid io.Reader. Therefore, you can call the Read method (as defined by io.Reader) on an object of type multipart.File.

`bufio.Writer` or `io.Writer`?

I have a function that writes data to anything that implements an interface with a Write(b []byte) (n int, err error) method. Right now in my program I write to an actual Conn, but following best practices (https://dave.cheney.net/2016/08/20/solid-go-design) and because I only call Write, I want to accept the minimum interface that implements that method. For that, I accept a parameter with interface io.Writer.
Since my function could be outputting lots of data very fast, should I be accepting a bufio.Writer instead? Or is it in the function’s consumer responsibility to use a buffered writer instead of a plain one? What are best practices?
Create your function to accept io.Writer, and document that it will write a lot of data, and so bufio.Writer or a similar construct is advised.
Do not limit users of your function to bufio.Writer, as you only use the functionality of an io.Writer. Also users may have other "buffered" implementation of io.Writer that will be sufficient for them.
Don't decide what's good for the users of your library, let them decide what's good for them. Should the users find bufio.Writer useful or better than their io.Writer implementation, they can always wrap it in a bufio.Writer and pass that (simply using bufio.NewWriter(w)).
If you create your function to accept io.Writer, users can always add the wrapping functionality very easily with a one-line utility function:
func wrapAndPass(w io.Writer) {
yourFunction(bufio.NewWriter(w))
}
If you create your function to accept bufio.Writer, then there is no way for the users to undo this "wrapping". Users will be forced to always create and pass a bufio.Writer, whether it's needed or not.
Also you may opt to provide two functions: your original function taking io.Writer, and the above wrapping-and-passing utility function. If you do so, it would also be nice to check if the passed writer is already a *bufio.Writer, in which case wrapping should be avoided. Something like this:
func wrapIfNeededAndPass(w io.Writer) {
if _, ok := w.(*bufio.Writer); !ok {
w = bufio.NewWriter(w)
}
yourFunction(w)
}
But usually this kind of wrapping is only applied if extra functionality is needed "beyond" io.Writer.

What is the difference in calling an interface methods and struct methods in serveHTTP handler?

I'm moving from Java to go. In 'go', I got confused when using a Handler.
For eg: ServeHTTP(w http.ResponseWriter, req *http.Request)
Here ResponseWriter is an interface and Request is a struct. We are using w as an object to call the methods in ResponseWriter interface. The same goes with req object. I know that a struct can implement an interface. Here I'm showing an example and where I'm getting confused. Go Playground Link
There's no difference. The interface is the type of your variable/field/parameter; the value is still (most likely) a struct. This is the same as in Java, where you can specify that a method argument is of an interface type, but you must still pass in a concretion. Calling methods on the interface-typed argument is the same as calling the method on a concrete type.

Can I subclass and redefine a method in Golang?

I'm using a Github Client that allows me to call github API methods more easily.
This library allows me to provide my own *http.Client when I initialize it:
httpClient := &http.Client{}
githubClient := github.NewClient(httpClient)
It works fine but now I need something else. I want to customize the Client so that every request (i.e. the Do method) gets a custom header added.
I've read a bit about embedding and this is what I've tried so far:
package trackerapi
import(
"net/http"
)
type MyClient struct{
*http.Client
}
func (my *MyClient)Do(req *http.Request) (*http.Response, error){
req.Header.Set("cache-control","max-stale=3600")
return my.Client.Do(req)
}
But the compiler does not let me use my custom MyClient in place of the default one:
httpClient := &trackerapi.MyClient{}
// ERROR: Cannot use httpClient (type *MyClient) as type
//*http.Client.
githubClient := github.NewClient(httpClient)
I'm a bit of a golang newbie so my question is: Is this the right way to do what I want to and, if not, what's the recommended approach?
Can I subclass ... in Golang?
Short answer: No. Go is not object oriented, therefore it has no classes, therefore subclassing is categorically an impossibility.
Longer answer:
You're on the right track with embedding, but you won't be able to substitute your custom client for anything that expects an *http.Client. This is what Go interfaces are for. But the standard library doesn't use an interface here (it does for some things, where it makes sense).
Another possible approach which may, depending on exact needs, work, is to use a custom transport, rather than a custom client. This does use an interface. You may be able to use a custom RoundTripper that adds the necessary headers, and this you can assign to an *http.Client struct.

How do I properly use these variables in a separate function in Go?

Apologies for what is likely a very elementary question.
I'm using http's listenAndServe, and it calls the following function:
func library(writer http.ResponseWriter, request *http.Request)
A lot of the code contained in that function applies elsewhere, so I wanted to bring it out into another function, such as:
func commonFunction(doThing bool, writer http.ResponseWriter, request *http.Request)
But is that function header for commonFunction correct if I'm passing those two variables from library into it?
Would I call it as commonFunction(true, writer, request)?
I'm mostly confused if I should be passing pointers to these variables? It would make sense not to for http.Request as it's already a pointer, but what about http.ResponseWriter, surely I don't want to recreate the variable?
Your signature looks fine. One part many people overlook when they first start doing web work in Go is that the writer http.ResponseWriter is an interface value. In Go interface values are reference types meaning that the writer variable you're being passed already internally contains a pointer to the concrete value that's satisfying that interface. You can feel free to pass your writer on to commonFunction and it's already a reference.

Resources