web-dev-qa-db-ja.com

GETリクエストを実行し、クエリ文字列を作成します

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

この例では、値がapiキーのapi_keyのGET変数を必要とするURLがあることがわかります。問題は、これが次の形式でハードコーディングされることです。

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

このクエリ文字列を動的に作成する方法はありますか?現時点では、有効な応答を得るために、このステップの前にURLを組み立てる必要があります。

51
Rudi Strydom

コメンターが述べたように、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

150
jcbwlkr

既存のクエリに追加する場合は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
}
20
allyraza

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

0
Janek Olszak