执行 GET 请求并构建查询字符串

问题描述 投票:0回答:4

我对 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,它需要 api_key 的 GET 变量,并以您的 api key 作为值。问题是这会以以下形式硬编码:

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

有没有办法动态构建这个查询字符串?目前,我需要在此步骤之前组装 URL,以获得有效的响应。

http go
4个回答
315
投票

正如评论者提到的,您可以从

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


60
投票

在附加到现有查询时使用

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
}

60
投票

仅使用

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
投票

它工作正常,我已经测试了这段代码:

package main
import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func main() {

    url := "https://example.com"

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Add("Accept", "application/json")
    req.Header.Add("Api-Key", "XXXXXXXXXXXX")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()

    // print all the response headers
    fmt.Println("Response headers:")
    for k, v := range resp.Header {
        fmt.Printf("%s: %s\n", k, v)
    }

    fmt.Println("Status:", resp.Status)

    data, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(data))


}
© www.soinside.com 2019 - 2024. All rights reserved.