Переходите к выполнению запроса GET и строите Querystring
Я новичок в Go и до сих пор не совсем понимаю. Во многих современных языках Node.js, Angular, jQuery, PHP вы можете выполнить запрос GET с дополнительными параметрами строки запроса.
Выполнение этого в Go не так просто, как кажется, и я пока не могу понять это. Я действительно не хочу, чтобы конкатенировать строку для каждого из запросов, которые я хочу сделать.
Вот пример 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))
}
В этом примере вы можете увидеть, что есть URL-адрес, для которого требуется переменная GET api_key с вашим ключом api в качестве значения. Проблема состоит в том, что это становится жестко закодированным в виде:
req, _ := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular?api_key=mySuperAwesomeApiKey", nil)
Есть ли способ построить эту строку запроса динамически? На данный момент мне нужно будет собрать URL-адрес до этого шага, чтобы получить действительный ответ.
Ответы
Ответ 1
Как отметил комментатор, вы можете получить 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
Ответ 2
Используйте 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
}
Ответ 3
Использование 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