Why can we use `nil` to get members

Viewed 143

I am studying http source codes of Golang, I found this

func NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*Request, error) {
    ...
    rc, ok := body.(io.ReadCloser)
    ...
}

but this body is nil, it is passed in the following way

func NewRequest(method, url string, body io.Reader) (*Request, error) {
    return NewRequestWithContext(context.Background(), method, url, body)
}
func (c *Client) Get(url string) (resp *Response, err error) {
    req, err := NewRequest("GET", url, nil)
    if err != nil {
        return nil, err
    }
    return c.Do(req)
}

Function Get passes nil to function NewRequest,

function NewRequest passes this nil to function NewRequestWithContext,

then function NewRequestWithContext use nil to call nil.(io.ReadCloser), why does not it cause panic?

2 Answers

The statement

    rc, ok := body.(io.ReadCloser)

tests if body is a ReadCloser. If not, then rc will be set to nil, and ok will be set to false.

If the code was:

rc:=body.(io.ReadCloser)

then with a nil body, it would panic.

The statement rc, ok := body.(io.ReadCloser) is a type assertion used in the assignment special form. When body is nil, rc is set to nil and ok is set to false.

Related