原文连接: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.cnblogs.com/phpper/p/16576423.html
本站部分图文来源于网络,如有侵权请联系删除。