2017-08-18 3 views
-1

Ich lerne Go und ich lese über Go offizielle Dokumentation net/http, und ich schreibe aus doc für Test folgenden Code:Warum ist http.Client {} mit & vorangestellt?

package main 

import (
    "net/http" 
    "fmt" 
) 

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

    fmt.Println(resp) 
} 

http.Client ist eine Strebe, aber ich weiß nicht, warum ein & gibt es Zeiger voran , Ich denke, erstellen Sie eine http.Client Referenz ist nicht notwendig, und warum client Variable haben Get Methode? Ich bin den Quellcode von „net/http“ zu lesen, es definierte Client Struktur unter:

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

Die Client Struktur nicht Get Methode definiert hat, aber warum client Variable Get Methode hat?

+0

Warum unten diese Frage abstimmen, geben Sie bitte einen Grund, so werde ich Aufmerksamkeit zu fragen. – TangMonk

+0

Weil es keinen Forschungsaufwand zeigt, bevor man die Frage stellt. Dies wird ausführlich in den [spec] (https://golang.org/ref/spec#Address_operators) und [tour] (https://tour.golang.org/moretypes/1) behandelt. – Adrian

+1

Aber der "Empfänger der Methode" wurde nicht in der Tour erwähnt, dies ist ein anderes Konzept mit anderen Sprachen, die der Lernende falsch versteht. Und übergeben Wert direkt an Funktion Parameter ist nur eine Kopie ohne Angabe mit einem Zeiger nicht in Tour auch erwähnt (ich benutze nie eine Sprache, die eine HTTP-Anfrage mit Zeiger direkt, Ruby, Java, Python, Elixier ...). Und das Lesen von Spezifikationen ist langweilig und lang, um eine neue Sprache zu lernen. Und ich glaube nicht, dass eine frischere Frage nicht wertvoll ist, man kann sehen, dass auch die letzte Antwort falsch ist, was bedeutet, dass manche Leute diese Sprache noch immer nicht verstehen. – TangMonk

Antwort

6

Ich würde wirklich die Go Tour nehmen, um zuerst ein Gefühl für die Sprache und ihre grundlegende Syntax zu bekommen.

Die Typdeklaration Sie zitierte enthält die Felder der Struktur, nicht aber seine Methoden. Methoden werden an anderer Stelle definiert, wie Funktionen, aber mit einem Empfänger hinzugefügt, der den Typ angibt, zu dem sie gehören. Dies ist beispielsweise die Definition von Client.Get() Methode:

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

der Teil vor dem Methodennamen wird der Empfänger genannt wird, und dass bestimmt die Art der Methode belogns bis (*Client in diesem Beispiel). Weitere Informationen finden Sie unter Spec: Method declarations.

Die & ist eine address operator, sie nimmt die Adresse ihres Operanden. In diesem Fall ist die lokale Variable client vom Typ *http.Client. http.Client{} ist ein composite literal, die einen Wert des Strukturtyps http.Client und & nimmt die Adresse des anonymen Variable erzeugt, wo dieser struct Wert gespeichert wird:

Taking the address eines Verbund Literal erzeugt einen Zeiger auf einen einzigartigen variable initialisiert mit der Wert des Literals.

Es wird verwendet, so dass der client Variable ein Zeiger auf einen http.Client Wert sein wird, eine, die gemeinsam genutzt werden wird gefördert und erneut verwendet werden:

Der typischerweise interner Zustand hat Transport des Kunden (im Cache TCP-Verbindungen), so dass Clients wiederverwendet werden sollten, anstatt sie nach Bedarf zu erstellen. Clients sind sicher für die gleichzeitige Verwendung durch mehrere Gloutines.

Und wenn client ein Zeiger ist, können Sie es laufen um zu anderen Funktionen, nur der Zeigerwert kopiert wird, nicht die spitze http.Client Struktur, so dass die Struktur selbst (http.Client Wert) wird wiederverwendet . Wenn Sie keinen Zeiger verwenden, würden Sie die Struktur selbst kopieren und nicht erneut verwenden, wenn Sie sie an andere Funktionen übergeben würden.

Beachten Sie, dass in diesem einfachen Beispiel es nicht wirklich wichtig, wie auch wenn alle Methoden der http.Client mit Zeiger Empfänger deklariert sind, können Sie immer noch Zeiger Methoden auf nicht-Pointer-Variablen aufrufen können, als client.Get() eine Abkürzung für (&client).Get() wäre . Dies wird erwähnt in Spec: Calls:

Wenn x ist addressable und &x ‚s Methode Set enthält m, x.m() ist eine Abkürzung für (&x).m().

Also auch wenn das & Adreßoperator nicht in diesem einfachen Beispiel benötigt wird, ist es gut, die Gewohnheit, mit ihm zu halten, sollte das Beispiel wachsen oder sollten Sie Code schreiben, wo diese Angelegenheit tut (zB Sie rund um den Pass Client erstellt).

+0

danke, du rettest mich – TangMonk

Verwandte Themen