govin
govin

Reputation: 6733

How to use pointers

Let's say I have this function

func main() {
    x := 10
    change(&x)
}

func change(n *int) {

}

If I don't use in n *int the signature, the above function gives an error -

*cannot use &x (type int) as type int in argument to change

But why does the below example run fine without requiring a client *HTTPClient in the argument of send method though I'm passing a pointer in this case?

import (
  "net/http"
)

// HTTPClient interface for making http requests
type HTTPClient interface {
    Get(url string) (*http.Response, error)
}


func main() {
    client := &http.Client{}
    err := send(client, url)
}

func send(client HTTPClient, url string) error {
}

Upvotes: 0

Views: 282

Answers (3)

Himanshu
Himanshu

Reputation: 12685

You are implementing a HTTPClient interface which takes a function Get. In go lang spec it is defined as

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)
}

In above function *Client is a pointer receiver to method GET. Client is a struct declared in Go source. For more information on http.Client struct defined in net/http package Check out Golang Spec.

In your first example code you are passing a pointer to Change function.

package main

import (
    "fmt"
)

type A interface{
    Change(n *int)
} 

func main() {
    x := 10
    Change(&x)
}

func Change(n *int) {
    fmt.Println(*n+1)
}

Check working example on Go playground

Upvotes: 1

Zak
Zak

Reputation: 5898

HTTPClient is an interface, it defines a single method Get(...)

The client struct, from http.Client also has a get method, docs here.

func (c *Client) Get(url string) (resp *Response, err error) {
    // trimmed ...
}

Source code

You can see from the definition above that Get(url) has a "pointer receiver". This means that *http.Client defines the Get(url) method and not http.Client. This means that *httpClient implements the HTTPClient interface and not http.Client.

The last thing worth pointing out is that the go runtime will automatically dereference pointers if, the an interface is implemented by a "value receiver" and not a "pointer receiver".

An example of this could be:

type Valuer interface {
    Value() string
}

type V struct {}

type (valueReceiver V) Value() string {
    // trimmed ...
}

// Here given a *V not V, go will dereference *V to call the Value() method on V not *V
vPtr := &V{}
vPtr.Value()

Upvotes: 3

Ravi R
Ravi R

Reputation: 1782

http.Client has a Get method with a pointer receiver (https://golang.org/pkg/net/http/#Client.Get), having the same signature as required by your HTTPCLient interface, so it works !

Upvotes: 1

Related Questions