为什么http.Client {}以&?为前缀

时间:2017-08-18 08:06:06

标签: pointers go methods struct

我正在学习Go,我正在阅读Go关于net/http的官方文档,我在doc中编写以下代码进行测试:

package main

import (
    "net/http"
    "fmt"
)

func main() {
    client := &http.Client{}
    resp, _ := client.Get("http://example.com")

    fmt.Println(resp)
}

http.Client是一个支柱,但我不知道为什么有&指针作为前缀,我认为创建http.Client引用不是必需的,为什么client变量有Get方法?我正在阅读“net / http”的源代码,它在下面定义了Client结构:

type Client struct {
    Transport RoundTripper
    CheckRedirect func(req *Request, via []*Request) error
    Jar CookieJar
    Timeout time.Duration
}

Client结构没有定义Get方法,但为什么client变量有Get方法?

1 个答案:

答案 0 :(得分:10)

我真的会先使用Go Tour来了解语言及其基本语法。

您引用的类型声明仅包含结构的字段,但不包含方法。方法在别处定义,例如函数,但添加了 receiver ,它指定了它们所属的类型。例如,Client.Get()方法的定义是:

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

方法名称前面的部分称为接收器,它指定方法所属的类型(在此示例中为*Client)。有关详细信息,请参阅Spec: Method declarations

&address operator,它取其操作数的地址。在这种情况下,局部变量client的类型为*http.Clienthttp.Client{}composite literal,它创建结构类型http.Client的值,&获取存储此结构值的匿名变量的地址:

  复合文字的

Taking the address生成一个指向使用文字值初始化的唯一variable的指针。

使用它是为了使client变量成为指向http.Client值的指针,鼓励共享和重用它:

  

客户端的传输通常具有内部状态(缓存的TCP连接),因此应该重用客户端而不是根据需要创建客户端。客户可以安全地同时使用多个goroutine。

如果client是一个指针,你可以自由地将它传递给其他函数,只会复制指针值,而不是指向的http.Client结构,所以结构本身({ {1}}值)将被重用。如果您不使用指针,如果您将它传递给其他函数,结构本身将被复制而不会被重用。

请注意,在这个简单的示例中它并不重要,因为即使使用指针接收器声明http.Client的所有方法,您仍然可以在非指针变量上调用指针方法,如{{1} }将是http.Client的简写。这在Spec: Calls:

中提到
  

如果client.Get()addressable(&client).Get()的方法集包含x,则&xm的简写。

所以即使在这个简单的例子中不需要x.m()地址运算符,保持使用它的习惯是好的,如果示例增长,或者你应该编写重要的代码(例如,你传递创建的客户端。)