原文连接: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()
- }
复制代码- 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()
- }
复制代码- 通过上面的示例介绍,涉及了日常开发中各种场景的请求类型,基本满足了常规开发,以上只是示例,后端如何处理数据,大家可以自行解析参数返回试试。
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |