原文連接: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()
}
通過上面的示例介紹,涉及了日常開發中各種場景的請求型別,基本滿足了常規開發,以上只是示例,后端如何處理資料,大家可以自行決議引數回傳試試,
無論從事什么行業,只要做好兩件事就夠了,一個是你的專業、一個是你的人品,專業決定了你的存在,人品決定了你的人脈,剩下的就是堅持,用善良專業和真誠贏取更多的信任,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/501599.html
標籤:其他
