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

huangapple go评论88阅读模式
英文:

Go doing a GET request and building the Querystring

问题

我对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("发送请求到服务器时出错")
        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密钥。问题在于,这个值变成了硬编码的形式:

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

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

英文:

I am pretty new to Go and don't quite understand everything as yet. In many of the modern languages Node.js, Angular, jQuery, PHP you can do a GET request with additional query string parameters.

Doing this in Go isn't quite a simple as it seems, and I can't really figure it out as yet. I really don't want to have to concatenate a string for each of the requests I want to do.

Here is the sample script:

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

In this example you can see there is a URL, which requires a GET variable of api_key with your api key as the value. The problem being that this becomes hard coded in the form of:

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

Is there a way to build this query string dynamically?? At the moment I will need to assemble the URL prior to this step in order to get a valid response.

答案1

得分: 307

如评论者所提到的,您可以从net/url中获取Values,它具有一个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

英文:

As a commenter mentioned you can get Values from net/url which has an Encode method. You could do something like this (req.URL.Query() returns the existing 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

答案2

得分: 58

当你追加到现有查询时,请使用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)
    }

    // 如果你追加到现有查询,这样做就可以了
    q := req.URL.Query()
    q.Add("api_key", "key_from_environment_or_flag")
    q.Add("another_thing", "foo & bar")

    // 或者你可以创建一个新的url.Values结构体,然后进行编码,如下所示
    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())
    // 输出:
    // http://api.themoviedb.org/3/tv/popularanother_thing=foo+%26+bar&api_key=key_from_environment_or_flag
}
英文:

Use r.URL.Query() when you appending to existing query, if you are building new set of params use the url.Values struct like so

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
}

答案3

得分: 56

使用NewRequest仅仅为了创建一个URL是过度的。可以使用net/url包:

package main

import (
	"fmt"
	"net/url"
)

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

	// 路径参数
	base.Path += "this will get automatically encoded"

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

	fmt.Printf("编码后的URL为 %q\n", base.String())
}

Playground: https://play.golang.org/p/YCTvdluws-r

英文:

Using NewRequest just to create an URL is an overkill. Use the net/url package:

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

Playground: https://play.golang.org/p/YCTvdluws-r

huangapple
  • 本文由 发表于 2015年6月5日 03:32:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/30652577.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定