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


90

私は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をアセンブルする必要があります。


1
では、文字列を連結することの何が問題になっていますか?
サルバドールダリ2015年

4
私は何も思いませんが、それは本当にエレガントな解決策ではなく、Goで物事を行うためのより良い方法があると思っただけです。アクションの変更とメソッドが表示されたら、すべてをつなぎ合わせる必要があります。
Rudi Strydom 2015年

2
url.ValuesEncode方法を使用できます。URL.StringURL全体を構築するために使用することもできます。
デイブC

回答:


213

コメント提供者が述べたように、あなたは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
素晴らしいありがとうございます!それがまさに私が探していたものです!
Rudi Strydom 2015年

テストにも最適です!
カイルチャダ2017

クエリ文字列パラメータを希望の順序で作成するためのソリューションはありますか?キーはEncode()メソッドでソートされます。
artificerpi

1
@artificerpi何らかの理由で重要な場合は、Encodeメソッドgolang.org/src/net/url/url.go?s=24222:24253#L845内で実行することを再実装できますが、なぜそれが重要なのか疑問に思います。
jcbwlkr

3
NewRequestを使用していない場合は、NewRequestを使用する必要はありません。url.Parse("https://something.com/")代わりに使用することも、URLオブジェクトを直接作成することもできます。
リチャード

36

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
}

14

使用してNewRequestURLを作成するだけのことはやりすぎです。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


同意しました、素晴らしい答えです!
POW-IL

これは本当に受け入れられた答えであるはずです。
ポール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.