GET isteği yapmaya ve Querystring'i oluşturmaya gidin


90

Go konusunda oldukça yeniyim ve henüz her şeyi tam olarak anlamıyorum. Modern Node.js, Angular, jQuery, PHP dillerinin çoğunda ek sorgu dizesi parametreleriyle bir GET isteği yapabilirsiniz.

Bunu Go'da yapmak göründüğü kadar basit değil ve henüz tam olarak anlayamıyorum. Yapmak istediğim her istek için bir dizeyi birleştirmek zorunda kalmayı gerçekten istemiyorum.

İşte örnek komut dosyası:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
)

func main() {
    client := &http.Client{}

    req, _ := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular", nil)
    req.Header.Add("Accept", "application/json")
    resp, err := client.Do(req)

    if err != nil {
        fmt.Println("Errored when sending request to the server")
        return
    }

    defer resp.Body.Close()
    resp_body, _ := ioutil.ReadAll(resp.Body)

    fmt.Println(resp.Status)
    fmt.Println(string(resp_body))
}

Bu örnekte, değer olarak api anahtarınızla birlikte api_key'in bir GET değişkenini gerektiren bir URL olduğunu görebilirsiniz. Sorun, bunun şu şekilde kodlanmış olmasıdır:

req, _ := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular?api_key=mySuperAwesomeApiKey", nil)

Bu sorgu dizesini dinamik olarak oluşturmanın bir yolu var mı? Şu anda, geçerli bir yanıt alabilmek için bu adımdan önce URL'yi bir araya getirmem gerekecek.


1
Öyleyse bir dizgeyi birleştirmenin nesi yanlış?
Salvador Dali

4
Sanırım hiçbir şey yok, ama bu gerçekten zarif bir çözüm değil, sadece Go'da işleri yapmanın daha iyi bir yolu olduğunu düşündüm. Eylem değişikliklerini, yöntemi görürsünüz ve sonra her şeyi bir araya getirmeniz gerekir.
Rudi Strydom

2
Sen kullanabilirsiniz url.Valuesbireyin Encodeyöntemi. URL.StringTüm URL'yi oluşturmak için de kullanabilirsiniz .
Dave C

Yanıtlar:


213

Bir yorumcunun bahsettiği gibi Values, net/urlhangisinin bir Encodeyöntemi olduğunu öğrenebilirsiniz . Bunun gibi bir şey yapabilirsin ( req.URL.Query()mevcut olanı döndürür url.Values)

package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    req, err := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular", nil)
    if err != nil {
        log.Print(err)
        os.Exit(1)
    }

    q := req.URL.Query()
    q.Add("api_key", "key_from_environment_or_flag")
    q.Add("another_thing", "foo & bar")
    req.URL.RawQuery = q.Encode()

    fmt.Println(req.URL.String())
    // Output:
    // http://api.themoviedb.org/3/tv/popular?another_thing=foo+%26+bar&api_key=key_from_environment_or_flag
}

http://play.golang.org/p/L5XCrw9VIG


1
Harika teşekkürler dostum! Tam olarak aradığım buydu!
Rudi Strydom

Test etmek için de harika!
Kyle Chadha

Sorgu dizesi parametrelerini istediğiniz sırada yapmak için herhangi bir çözüm var mı? Anahtarlar Encode()yöntemde sıralanmıştır .
artificerpi

1
@artificerpi eğer bir sebepten ötürü kritikse , Encode yönteminde yaptıklarını yeniden uygulayabilirdiniz golang.org/src/net/url/url.go?s=24222:24253#L845 Ama bunun neden önemli olduğunu merak ediyorum.
jcbwlkr

3
Onunla hiçbir şey yapmıyorsanız, NewRequest'i kullanmanıza gerek yoktur. Bunun url.Parse("https://something.com/")yerine kullanabilir veya doğrudan bir URL nesnesi oluşturabilirsiniz.
Richard

36

Kullanım r.URL.Query()varolan sorguya ekleme yaparken params dizi yeni inşa ediyoruz eğer kullanmak url.Valuesşöyle yapı

package main

import (
    "fmt"
    "log"
    "net/http"
    "net/url"
    "os"
)

func main() {
    req, err := http.NewRequest("GET","http://api.themoviedb.org/3/tv/popular", nil)
    if err != nil {
        log.Print(err)
        os.Exit(1)
    }

    // if you appending to existing query this works fine 
    q := req.URL.Query()
    q.Add("api_key", "key_from_environment_or_flag")
    q.Add("another_thing", "foo & bar")

    // or you can create new url.Values struct and encode that like so
    q := url.Values{}
    q.Add("api_key", "key_from_environment_or_flag")
    q.Add("another_thing", "foo & bar")

    req.URL.RawQuery = q.Encode()

    fmt.Println(req.URL.String())
    // Output:
    // http://api.themoviedb.org/3/tv/popularanother_thing=foo+%26+bar&api_key=key_from_environment_or_flag
}

14

NewRequestYalnızca bir URL oluşturmak için kullanmak abartıdır. net/urlPaketi kullanın :

package main

import (
    "fmt"
    "net/url"
)

func main() {
    base, err := url.Parse("http://www.example.com")
    if err != nil {
        return
    }

    // Path params
    base.Path += "this will get automatically encoded"

    // Query params
    params := url.Values{}
    params.Add("q", "this will get encoded as well")
    base.RawQuery = params.Encode() 

    fmt.Printf("Encoded URL is %q\n", base.String())
}

Oyun alanı: https://play.golang.org/p/YCTvdluws-r


Kabul edildi, harika cevap!
pow-il

Bu gerçekten kabul edilen cevap olmalı.
Paul
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.