英文:
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
}
答案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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论