Jestem całkiem nowy w Go i jeszcze nie do końca wszystko rozumiem. W wielu współczesnych językach Node.js, Angular, jQuery, PHP można wykonać żądanie GET z dodatkowymi parametrami ciągu zapytania.
Robienie tego w Go nie jest takie proste, jak się wydaje, i nie mogę jeszcze tego rozgryźć. Naprawdę nie chcę łączyć łańcucha dla każdego żądania, które chcę wykonać.
Oto przykładowy skrypt:
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))
}
W tym przykładzie widać, że istnieje adres URL, który wymaga zmiennej GET api_key z kluczem api jako wartością. Problem polega na tym, że zostaje to zakodowane w postaci:
req, _ := http.NewRequest("GET", "http://api.themoviedb.org/3/tv/popular?api_key=mySuperAwesomeApiKey", nil)
Czy istnieje sposób dynamicznego tworzenia tego ciągu zapytania? W tej chwili będę musiał zebrać adres URL przed tym krokiem, aby uzyskać prawidłową odpowiedź.
url.Values
''Encode
. Możesz również użyćURL.String
do zbudowania całego adresu URL.Odpowiedzi:
Jak wspomniał komentator, możesz uzyskać,
Values
znet/url
którego maEncode
metodę. Możesz zrobić coś takiego (req.URL.Query()
zwraca istniejącyurl.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
źródło
Encode()
metody.url.Parse("https://something.com/")
zamiast tego lub nawet bezpośrednio utworzyć obiekt URL.Użyj
r.URL.Query()
podczas dołączania do istniejącego zapytania, jeśli budujesz nowy zestaw parametrów, użyjurl.Values
struktury w ten sposóbpackage 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 }
źródło
Używanie
NewRequest
samego tylko do tworzenia adresu URL to przesada. Skorzystaj znet/url
pakietu: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()) }
Plac zabaw: https://play.golang.org/p/YCTvdluws-r
źródło