原文連接:https://www.zhoubotong.site/post/67.html Go 標準庫的net/url包提供的兩個函可以直接檢查URL合法性,不需要手動去正則匹配校驗。 下麵可以直接使用ParseRequestURI()函數解析URL,當然這個只會驗證url格式,至於功能變數名稱是否存在或 ...
原文連接:https://www.zhoubotong.site/post/67.html
Go 標準庫的net/url包提供的兩個函可以直接檢查URL合法性,不需要手動去正則匹配校驗。
下麵可以直接使用ParseRequestURI()函數解析URL,當然這個只會驗證url格式,至於功能變數名稱是否存在或註冊,不會檢查的,舉個例子:
package main import ( "fmt" "net/url" ) func main() { url, err := url.ParseRequestURI("https://www.zhoubotong.site") // 註意這裡必須帶有http/https協議, //否則會被認定非合法url,但是使用//www.zhoubotong.sit,被返回空,所以error哪裡會被繞過,該示例代碼不夠嚴謹 if err != nil { fmt.Println(err) return } fmt.Println(url.Hostname()) }
輸出:[www.zhoubotong.site](http://www.zhoubotong.site),下麵整個錯誤的url:
func main() { url, err := url.ParseRequestURI("www.zhoubotong.site") // www.zhoubotong.site" 或者zhoubotong.site" if err != nil { fmt.Println(err) return } fmt.Println(url.Hostname()) }
輸出:parse "www.zhoubotong.site": invalid URI for request,既然上面的代碼不夠嚴謹,如何改善呢?完整代碼如下:
package main import ( "fmt" "net/url" ) func main() { var u string = "https://www.zhoubotong.site" _, err := url.ParseRequestURI(u) if err != nil { fmt.Println(err) return } url, err := url.Parse(u) if err != nil || url.Scheme == "" || url.Host == "" { fmt.Println(err) return } fmt.Println(url.Hostname(), "success") }
通過上面的兩個函數解析url鏈接,順便嘮叨介紹下這塊http/post請求的示例,Get請求示例:
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "time" ) // 定義返回的響應體 type Response struct { Params string `json:"params"` Headers map[string]string `json:"headers"` Origin string `json:"origin"` Url string `json:"url"` } var remoteUrl string = "https://www.baidu.com" // 獲取帶參數的http get請求響應數據 func getUrlParse() { data := url.Values{} data.Set("username", "喬峰") data.Set("sex", "male") u, err := url.ParseRequestURI(remoteUrl) if err != nil { fmt.Println(err) } u.RawQuery = data.Encode() fmt.Println(u.RawQuery) resp, err := http.Get(u.String()) if err != nil { fmt.Println(err) } defer resp.Body.Close() // 一定要關閉釋放tcp連接 body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) } fmt.Println(string(body)) } // 解析get請求的返回的json結果到struct func getResultToStruct() { resp, err := http.Get(remoteUrl) if err != nil { fmt.Println(err) return } defer resp.Body.Close() var res Response // 定義res為Responser結構體 body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println(err) return } _ = json.Unmarshal(body, &res) // 註意這裡是&res 地址引用 fmt.Printf("%#v\n", res) } //get 請求添加頭消息 func getHttpByHeader() { param := url.Values{} param.Set("username", "babala") param.Set("sex", "female") u, _ := url.ParseRequestURI(remoteUrl) u.RawQuery = param.Encode() // 把參數轉換成 sex=female&username=babala fmt.Println(u) //重點註意:如果我們直接使用預設的http,那麼它是沒有超時時間的。這樣就會帶來性能問題,具體稍後寫一篇詳細介紹這塊 client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest("GET", u.String(), nil) if err != nil { fmt.Println(err) } // 添加請求頭header 參數 req.Header.Add("username2", "風清揚") req.Header.Add("age1", "89") resp, _ := client.Do(req) defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } fmt.Println(string(body)) } func main() { getResultToStruct() getHttpByHeader() }
發送post請求示例:
package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "strings" "time" ) var remoteUrl = "https://www.zhoubotong.site" // 發送表單post請求 func postByForm() { param := url.Values{} param.Add("username", "喬峰") param.Add("sex", "male") resp, _ := http.PostForm(remoteUrl, param) // 表單提交"Content-Type": "application/x-www-form-urlencoded" defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } // 發送表單提交,可以對比上面的postByForm的實現差異 func postByForm2() { urlValue := url.Values{ "username": {"喬峰"}, "sex": {"male"}, } respData := urlValue.Encode() fmt.Println(respData) // encode轉碼:name=%E4%B9%94%E5%B3%B0&sex=male resp, _ := http.Post(remoteUrl, "text/html", strings.NewReader(respData)) //註意接收數據類型為text/html,對應在postman中的x-www-form-urlencoded中的key value參數 defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } // 發送json數據 func postJson() { client := &http.Client{Timeout: time.Second * 10} param := make(map[string]interface{}) param["username"] = "喬峰" param["sex"] = "male" respdata, _ := json.Marshal(param) // respdata[]byte類型,轉化成string類型便於查看 req, _ := http.NewRequest("POST", remoteUrl, bytes.NewReader(respdata)) //http.NewRequest請求會自動發送header中的Content-Type為applcation/json,對應在postman中的body的raw的json參數 resp, _ := client.Do(req) body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } // 發送json數據,註意和上面實現的區別 func postJson2() { param := make(map[string]interface{}) param["username"] = "喬峰" param["sex"] = "male" respdata, _ := json.Marshal(param) // respdata[]byte類型,轉化成string類型便於查看 fmt.Println(string(respdata)) resp, _ := http.Post(remoteUrl, "application/json", bytes.NewReader(respdata)) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } /* 對應的postman中params中的key value參數,我估計很多人都很迷惑postman工具的params和body兩個地方傳遞參數的區別, 其實Params處設置的變數請求時會url後問號傳參(?x=y)。而Body里設置的參數則是介面真正請求時發的參數,下麵這個例子就是通過params傳參 */ func postString() { param := url.Values{} param.Add("username", "babala") param.Add("sex", "female") u, _ := url.ParseRequestURI(remoteUrl) u.RawQuery = param.Encode() fmt.Println(u) client := &http.Client{} req, _ := http.NewRequest("POST", u.String(), nil) // 註意發送數據類似為string的post請求,對應的postman中params中的key value參數 resp, _ := client.Do(req) defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) fmt.Println(string(body)) } func main() { //postByForm() //postByForm2() //postJson() //postJson2() postString() }
通過上面的示例介紹,涉及了日常開發中各種場景的請求類型,基本滿足了常規開發,以上只是示例,後端如何處理數據,大家可以自行解析參數返回試試。
無論從事什麼行業,只要做好兩件事就夠了,一個是你的專業、一個是你的人品,專業決定了你的存在,人品決定了你的人脈,剩下的就是堅持,用善良專業和真誠贏取更多的信任。