在Go中将interface {}参数转换为* http.Request或* http.Response

I'm tying to create an util function that will read body of the Request/Response and return it.
Here's what I've done for the moment:

func GetBody(in interface{}) []byte {
    var body io.Reader
    var statusCode int

    switch v := in.(type) {
        case *http.Request, *http.Response:
            body = v.Body
            statusCode = v.StatusCode
        default:
            log.Fatal("Only http.Request and http.Response parameters can be accepted to parse body")
    }

    if statusCode != 200 {
        log.Fatalf("Received status code [%d] instead of [200]", statusCode)
    }

    body, err := ioutil.ReadAll(body)
    if err != nil {
        log.Fatal(err)
    }
    return body
}

But I'm receiving an error of compiler: v.Body undefined (type interface {} is interface with no methods)
Am I missing something or it's impossible to make a generic function that will server both for *http.Request and *http.Response

What you are trying to do is more something like that:

switch in.(type) {
    case *http.Request:
        body = v.(*http.Request).Body
    case *http.Response:
        body = v.(*http.Response).Body
    default:
        log.Fatal(...)
}

EDIT: I removed the wrong part of my answer, see HectorJ's answer for the more syntaxic please way of doing this.

It is because of the double case.

v is still an interface{} because it could be either an *http.Request or an *http.Response

switch v := in.(type) {
    case *http.Request
        body = v.Body
        statusCode = v.StatusCode
    case *http.Response:
        body = v.Body
        statusCode = v.StatusCode
    default:
        log.Fatal("Only http.Request and http.Response parameters can be accepted to parse body")
}

This should work

In addition to the other answers which directly address the issue with your type switch, I'd like to point out an alternative solution. Note, the interface{} solution is perfectly fine and may easily be considered preferable to this. This is presented for edification.

First, as a slight aside, if the thing you were interested in was a common method (e.g. Write or Cookies) rather than a common field (Body), it would be easy and better to access it via a custom interface.

Either by defining a type:

type cookier interface { // Should probably use a better name
    Cookies() []*http.Cookie
}  
func ShowCookies1(r cookier) {
    log.Println("Got cookies:", r.Cookies())
}

Or by using an anonymous type in the function definition:

func ShowCookies2(r interface {
    Cookies() []*http.Cookie
}) {
    log.Println("Got cookies:", r.Cookies())
}

These functions can accept anything that has a Cookies method, this includes *http.Request and *http.Response.

Unfortunately, in your particular case you wish to access a common field rather than a common method so you can't directly just use a matching interface.

You could make a small wrapper type that adds a GetBody method (one could argue such a function should have been defined in the standard package).

type reqbody struct{ *http.Request }
type respbody struct{ *http.Response }
type getbody interface {
    GetBody() io.ReadCloser
}

func (r reqbody) GetBody() io.ReadCloser  { return r.Body }
func (r respbody) GetBody() io.ReadCloser { return r.Body }

func GetBody2(r getbody) ([]byte, error) {
    body := r.GetBody()
    defer body.Close()
    return ioutil.ReadAll(body)
}

The caller knows what type they have and does one of:

    buf, err = GetBody2(reqbody{req})
    buf, err = GetBody2(respbody{resp})

In some sense this is uglier than just using interface{}. But it has the benefit that instead of having a function that takes absolutely any type and panics/errors at run-time if a programmer mistakenly calls it with something not of the appropriate type, this instead forces the caller to safely pass something you known is of the correct type at compile time.

Looking at this further, you're just reading everything from an io.ReadCloser and then closing it so it could further be simplified to the following (which probably is better than your interface{} solution):

func GetReqBody(r *http.Request) io.ReadCloser   { return r.Body }
// Could add checking r.StatusCode to the following one as well:
func GetRespBody(r *http.Response) io.ReadCloser { return r.Body }
func ReadAndClose(rc io.ReadCloser) ([]byte, error) {
    defer rc.Close()
    return ioutil.ReadAll(rc)
}

Again, the caller knows what type they have and does one of:

    buf, err = ReadAndClose(GetReqBody(req))
    buf, err = ReadAndClose(GetRespBody(resp))

Or just:

    buf, err = ReadAndClose(req.Body)
    buf, err = ReadAndClose(resp.Body)

You can see an example of all these options on the Go Playground.

Finally, be careful using ioutil.ReadAll. Often it is better to avoid pre-reading an entire file or network steam into a buffer and instead process it as a stream as it is being read. In particular, it's trivial to make an HTTP request with an arbitrary large body as a denial of service attack or to waste server resources (http.MaxBytesReader can also help).