ไปทำคำขอ GET และสร้าง Querystring


90

ฉันค่อนข้างใหม่สำหรับ 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 ซึ่งต้องใช้ตัวแปร GET ของ api_key พร้อมกับคีย์ api ของคุณเป็นค่า ปัญหาคือสิ่งนี้กลายเป็นรหัสยากในรูปแบบของ:

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

มีวิธีสร้างสตริงแบบสอบถามนี้แบบไดนามิกหรือไม่? ในขณะนี้ฉันจะต้องรวบรวม URL ก่อนขั้นตอนนี้เพื่อให้ได้รับคำตอบที่ถูกต้อง


1
เกิดอะไรขึ้นกับการเชื่อมสตริงเข้าด้วยกัน?
Salvador Dali

4
ฉันคิดว่าไม่มีอะไรเลย แต่มันไม่ใช่วิธีการละลายที่สวยงามเพียงแค่คิดว่ามีวิธีที่ดีกว่าในการทำสิ่งต่างๆใน Go คุณเห็นการกระทำเปลี่ยนไปวิธีการและจากนั้นคุณต้องรวมทุกอย่างเข้าด้วยกัน
Rudi Strydom

2
คุณสามารถใช้url.Values's Encodeวิธี คุณยังสามารถใช้URL.Stringเพื่อสร้าง URL ทั้งหมด
Dave C

คำตอบ:


213

ในฐานะที่เป็นผู้แสดงความคิดเห็นพูดถึงคุณจะได้รับ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


1
สุดยอดขอบคุณคน! นั่นคือสิ่งที่ฉันกำลังมองหา!
Rudi Strydom

เหมาะสำหรับการทดสอบด้วย!
Kyle Chadha

วิธีใดในการสร้างพารามิเตอร์สตริงการสืบค้นตามลำดับที่คุณต้องการ? คีย์จะเรียงตามEncode()วิธีการ
artificerpi

1
@artificerpi หากมีความสำคัญด้วยเหตุผลบางประการคุณสามารถนำสิ่งที่พวกเขาทำกลับมาใช้ใหม่ในวิธีการเข้ารหัสgolang.org/src/net/url/url.go?s=24222:24253#L845แต่ฉันจะสงสัยว่าทำไมมันถึงมีความสำคัญ
jcbwlkr

3
คุณไม่จำเป็นต้องใช้ NewRequest หากคุณไม่ได้ทำอะไรกับมัน คุณสามารถใช้url.Parse("https://something.com/")แทนหรือสร้างออบเจ็กต์ URL ได้โดยตรง
Richard

36

ใช้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
}

14

การใช้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


เห็นด้วยคำตอบที่ดี!
pow-il

นี่ควรเป็นคำตอบที่ยอมรับได้จริงๆ
พอล
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.