Виконайте GET-запит і створіть Querystring


85

Я зовсім новачок у Go, і поки що не зовсім все розумію. У багатьох сучасних мовах Node.js, Angular, jQuery, PHP ви можете зробити запит GET із додатковими параметрами рядка запиту.

Зробити це в Go не так просто, як здається, і я поки що не можу це зрозуміти. Я дійсно не хочу об'єднувати рядок для кожного із запитів, які я хочу зробити.

Ось зразок сценарію:

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

У цьому прикладі ви можете бачити, що є URL-адреса, яка вимагає GET змінну api_key з вашим ключем api як значенням. Проблема полягає в тому, що це стає жорстко закодованим у вигляді:

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

Чи є спосіб побудувати цей рядок запиту динамічно ?? На даний момент мені потрібно буде зібрати URL-адресу перед цим кроком, щоб отримати дійсну відповідь.


1
То що не так із об’єднанням рядка?
Сальвадор Далі

4
Я гадаю, нічого, але насправді це не елегантне рішення, просто подумав, що в Go є кращий спосіб зробити щось. Ви бачите зміни дії, метод, а потім вам доведеться все об’єднати.
Руді Стридом

2
Ви можете використовувати метод url.Values' Encode. Ви також можете використати URL.Stringдля створення цілої URL-адреси.
Dave C

Відповіді:


208

Як уже згадувалося коментатор ви можете отримати Valuesз net/urlяких має Encodeметод. Ви можете зробити щось подібне ( req.URL.Query()повертає існуюче 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
Дивовижне спасибі людино! Це саме те, що я шукав!
Руді Стридом

Чудово підходить і для тестування!
Кайл Чадха,

Будь-яке рішення для створення параметрів рядка запиту у вашому бажаному порядку? Ключі відсортовані за Encode()методом.
artificerpi

1
@artificerpi, якщо це було критично з якихось причин, ви могли б реалізувати те, що вони роблять у методі Encode golang.org/src/net/url/url.go?s=24222:24253#L845 Але мені було б цікаво, чому це мало значення.
jcbwlkr

3
Вам не потрібно використовувати NewRequest, якщо ви з ним нічого не робите. Ви можете просто використовувати url.Parse("https://something.com/")замість цього або навіть безпосередньо створити об'єкт URL-адреси.
Річард

34

Використовуйте r.URL.Query()при додаванні до існуючого запиту, якщо ви створюєте новий набір параметрів, використовуйте url.Valuesструктуру так

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
}

11

Використання NewRequestпросто для створення URL-адреси є надмірним. Використовуйте net/urlпакет:

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

Дитячий майданчик: https://play.golang.org/p/YCTvdluws-r


найпростіша відповідь і працювали ідеально, дякую
Джейк Бумгарден
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.