1. strings —字符串函数:
    1. 包含:
      fmt.Println(strings.Contains("abc","a"))  // 输出 true
    2. 分割:
      fmt.Println(strings.Split("a,b,c",","))  // 输出 [a b c]
    3. 拼接:
      fmt.Println(strings.Join([]string{"a","b","c"},","))  // 输出 a,b,c
    4. 去除首尾指定字符:
      fmt.Println(strings.Trim("-!abc#","-#!"))  // 输出 abc
    5. 替换:
      fmt.Println(strings.Replace("abc","b","-",1))  // 输出 a-c
    6. 重复字符串:
      fmt.Println(strings.Repeat("a",3))  // 输出 aaa
    7. 检索位置:
      fmt.Println(strings.Index("abc","b"))  // 输出 1
    8. 去除空格:
      fmt.Println(strings.Fields(" a b c "))  // 输出 [a b c]
      fmt.Println(strings.TrimSpace(" a b c "))  // 输出 a b c(前后无空格)
    9. 截取:
      fmt.Println(string([]rune("abc你好吗")[1:5]))  // 输出 bc你好
    10. 将字符串转换为 io.reader(goquery 会用到):
      fmt.Println(strings.NewReader("abc"))  // 输出 &{abc 0 -1}
  2. strconv —字符串转换:
    1. Append —将其它类型添加到 byte 切片中:
      1. 整型:
        fmt.Println(string(strconv.AppendInt([]byte("abc"),1000,10)))  // 输出 abc1000
      2. 布尔:
        fmt.Println(string(strconv.AppendBool([]byte("abc"),false)))  // 输出 abcfalse
      3. 字符串:
        fmt.Println(string(strconv.AppendQuote([]byte("abc"),"你好吗")))  // 输出 abc"你好吗"
    2. Format —其它类型转字符串:
      1. 整型:
        fmt.Println(strconv.Itoa(1000))  // 输出 1000
      2. 浮点型:
        fmt.Println(strconv.FormatFloat(3.1415926, 'g', 3, 64))  // 输出 3.14
      3. 布尔:
        fmt.Println(strconv.FormatBool(false))  // 输出 false
    3. Parse —字符串转为其它类型:
      1. 整型:
        fmt.Println(strconv.Atoi("1000"))  // 输出 1000 <nil>
      2. 浮点型:
        fmt.Println(strconv.ParseFloat("3.1415926",64))  // 输出 3.1415926 <nil>
      3. 布尔:
        fmt.Println(strconv.ParseBool("false"))  // 输出 false <nil>
    4. Quote —特殊字符转义:
      fmt.Println(strconv.Quote(`abc\r\s\t`))  // 输出 "abc\\r\\s\\t"
    5. 其它:
      1. string 转 []byte:
        str := "abc"
        fmt.Println([]byte(str))
      2. []byte 转 string:
        bt := []byte{97,98,99}
        fmt.Println(string(bt))
  3. encoding —编解码
    1. encoding/json —生成/解析 json:
      1. 生成:
        package main
        import (
        "encoding/json"
        "fmt"
        )
        type Student struct {
        Name string `json:"name"`
        }
        type PeopleList struct {
        People []Student `json:"people"`
        }
        func main()  {
        data := PeopleList{
        []Student{
        {Name:"xiaoming"},
        {Name:"xiaomei"},
        }}
        res,_ := json.Marshal(data)
        fmt.Println(string(res))
        }
        // 输出 {"people":[{"name":"xiaoming"},{"name":"xiaomei"}]}
      2. 解析:
        package main
        import (
        "encoding/json"
        "fmt"
        )
        type Student struct {
        Name string `json:"name"`
        }
        type PeopleList struct {
        People []Student `json:"people"`
        }
        func main()  {
        str := `{"people":[{"name":"xiaoming"},{"name":"xiaomei"}]}`
        var res PeopleList
        json.Unmarshal([]byte(str), &res)
        fmt.Println(res)
        }
        // 输出 {[{xiaoming} {xiaomei}]}
    2. encoding/xml —生成/解析 xml:
      1. 生成:
        package main
        import (
        "encoding/xml"
        "fmt"
        )
        type People struct {
        XMLName xml.Name `xml:"people"`
        Version string   `xml:"version,attr"`
        Svs     []Student `xml:"student"`
        }
        type Student struct {
        Name string `xml:"name"`
        }
        func main() {
        v := &People{Version: "1"}
        v.Svs = append(v.Svs, Student{Name:"xiaoming"})
        v.Svs = append(v.Svs, Student{Name:"xiaomei"})
        output,_ := xml.Marshal(v)
        fmt.Println(string([]byte(xml.Header)))
        fmt.Println(string(output))
        }
        // 输出
        <?xml version="1.0" encoding="UTF-8"?>
        <people version="1"><student><name>xiaoming</name></student><student><name>xiaomei</name></student></people>
      2. 解析:
        package main
        import (
        "encoding/xml"
        "fmt"
        )
        type People struct {
        XMLName     xml.Name `xml:"people"`
        Version     string   `xml:"version,attr"`
        Svs         []Student `xml:"student"`
        }
        type Student struct {
        Name string   `xml:"name"`
        }
        func main() {
        data := []byte(`
        <?xml version="1.0" encoding="utf-8"?>
        <people version="1">
        <student>
        <name>xiaoming</name>
        </student>
        <student>
        <name>xiaomei</name>
        </student>
        </people>
        `)
        v := People{}
        err := xml.Unmarshal(data, &v)
        if err != nil {
        fmt.Printf("error: %v", err)
        return
        }
        fmt.Println(v)
        }
        // 输出
        {{ people} 1 [{xiaoming} {xiaomei}]}
    3. encoding/hex —十六进制编/解码:
      package main
      import (
      "encoding/hex"
      "fmt"
      )
      func main() {
      str := []byte("hello")
      // 编码
      encode_str := hex.EncodeToString(str)
      fmt.Println(encode_str)  // 输出 68656c6c6f
      // 解码
      decode_byte, _ := hex.DecodeString(encode_str)
      fmt.Println(string(decode_byte))  // 输出 hello
      }
    4. encoding/base64 —BASE64加/解密:
      package main
      import (
      "encoding/base64"
      "fmt"
      )
      func base64Encode(str string) string {
      return base64.StdEncoding.EncodeToString([]byte(str))
      }
      func base64Decode(str string) (string, error){
      d,e := base64.StdEncoding.DecodeString(str)
      return string(d),e
      }
      func main(){
      str := "hello"
      enc_str := base64Encode(str)
      fmt.Println(string(enc_str))  // 输出 aGVsbG8=
      dec_str,_ := base64Decode(enc_str)
      fmt.Println(string(dec_str))  // 输出 hello
      }
  4. regexp —正则处理:
    1. 验证:
      fmt.Println(regexp.MatchString("[a-z]*","abc"))  // 输出 true <nil>
    2. 获取:
      r, _ := regexp.Compile("[0-9]")
      str := "a1b2c3"
      // 获取第一个元素
      m1 := r.FindString(str)
      fmt.Println(m1)  // 输出 1
      // 获取所有
      m2 := r.FindAllString(str,-1)
      fmt.Println(m2)  // 输出 [1 2 3]
    3. 替换:
      r, _ := regexp.Compile("[0-9]")
      str := "a1b2c3"
      ret := r.ReplaceAllString(str,"")
      fmt.Println(ret)  // 输出 abc
  5. crypto —加密/解密:
    1. crypto/md5 —MD5加密:
      package main
      import (
      "crypto/md5"
      "encoding/hex"
      "fmt"
      "io"
      )
      func Md5(str string) string {
      h := md5.New()
      io.WriteString(h, str)
      cipherStr := h.Sum(nil)
      return hex.EncodeToString(cipherStr)
      }
      func main() {
      ret := Md5("123456")
      fmt.Println(ret)  // 输出 e10adc3949ba59abbe56e057f20f883e
      }
    2. crypto/sha1 —SHA1加密:
      package main
      import (
      "crypto/sha1"
      "encoding/hex"
      "io"
      "fmt"
      )
      func Sha1(str string) string {
      h := sha1.New()
      io.WriteString(h, str)
      cipherStr := h.Sum(nil)
      return hex.EncodeToString(cipherStr)
      }
      func main(){
      ret := Sha1("123456")
      fmt.Println(ret)  // 输出 7c4a8d09ca3762af61e59520943dc26494f8941b
      }
    3. crypto/sha256 —SHA256加密:
      package main
      import (
      "crypto/sha256"
      "encoding/hex"
      "io"
      "fmt"
      )
      func Sha256(str string) string {
      h := sha256.New()
      io.WriteString(h, str)
      cipherStr := h.Sum(nil)
      return hex.EncodeToString(cipherStr)
      }
      func main(){
      ret := Sha256("123456")
      fmt.Println(ret)  // 输出 8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92
      }
  6. time —时间处理:
    1. 获取时间缀:
      fmt.Println(time.Now().Unix())  // 输出 1589153929
    2. 解析/格式化:
      package main
      import (
      "fmt"
      "time"
      )
      func main(){
      t,_ := time.ParseInLocation("2006/01月02日 15:04:05", "2019/08月11日 11:50:35", time.Local)
      fmt.Println(t.String())  // 输出 2019-08-11 11:50:35 +0800 PST
      fmt.Println(t.Year())  // 输出 2019
      fmt.Println(t.Format("2006-01-02 15:04:05"))  // 输出 2020-01-01 00:00:00(时间字符串)
      fmt.Println(t.Unix())  // 输出 1565495435(时间缀)
      }
    3. 生成:
      package main
      import (
      "fmt"
      "time"
      )
      func main() {
      t := time.Date(2019, 8, 11, 12, 11, 12, 0, time.Local)
      fmt.Println(t.String())  // 输出 2019-08-11 12:11:12 +0800 PST
      fmt.Println(t.Format("2006-01-02 15:04:05"))  // 输出 2020-01-01 00:00:00
      fmt.Println(t.Unix())  // 输出 1565496672
      }
    4. 获取整点时间:
      package main
      import (
      "fmt"
      "time"
      )
      func main() {
      t := time.Now()
      fmt.Println(t.String())  // 输出 2020-05-11 07:55:22.083553 +0800 PST m=+0.000083752
      fmt.Println(t.Truncate(time.Hour))  // 输出 2020-05-11 07:00:00 +0800 PST
      fmt.Println(t.Round(time.Hour))  // 输出 2020-05-11 08:00:00 +0800 PST
      }
    5. 时间加减:
      1. 相加(获取相加后的时间):
        package main
        import (
        "fmt"
        "time"
        )
        func main() {
        // Add 时间相加
        now := time.Now()
        // 1分钟后
        m, _ := time.ParseDuration("1m")
        m1 := now.Add(m)
        fmt.Println(m1)
        // 1小时后
        h, _ := time.ParseDuration("1h")
        h1 := now.Add(h)
        fmt.Println(h1)
        // 1天后
        d, _ := time.ParseDuration("24h")
        d1 := now.Add(d)
        fmt.Println(d1)
        }
        // 输出
        2020-09-22 08:42:39.49779 +0800 PST m=+60.000075164
        2020-09-22 09:41:39.49779 +0800 PST m=+3600.000075164
        2020-09-23 08:41:39.49779 +0800 PST m=+86400.000075164
      2. 相减(获取两个时间点相差的时间):
        package main
        import (
        "fmt"
        "time"
        )
        func main() {
        // Sub 计算两个时间差
        now := time.Now()
        // 1分钟前
        m, _ := time.ParseDuration("-1m")
        m1 := now.Add(m)
        // 1个小时前
        h, _ := time.ParseDuration("-1h")
        h1 := now.Add(h)
        // 1天前
        d, _ := time.ParseDuration("-24h")
        d1 := now.Add(d)
        subM := now.Sub(m1)
        fmt.Println(subM.Minutes(), "分钟")
        sumH := now.Sub(h1)
        fmt.Println(sumH.Hours(), "小时")
        sumD := now.Sub(d1)
        fmt.Printf("%v 天\n", sumD.Hours()/24)
        }
        // 输出
        1 分钟
        1 小时
        1
    6. 计时器:
      1. 一次性:
        package main
        import (
        "fmt"
        "time"
        )
        func main() {
        fmt.Println(time.Now().Second())  // 输出 6
        timer := time.NewTimer(time.Second * 3)  // 计时 3秒
        <- timer.C
        fmt.Println(time.Now().Second())  // 输出 9
        }
      2. 周期性:
        package main
        import (
        "fmt"
        "time"
        )
        func main() {
        ticker := time.NewTicker(time.Second * 1)
        i := 0
        for {
        <- ticker.C
        fmt.Println(time.Now().Second())
        i++
        if i == 3 {
         ticker.Stop() // 停止定时器
         break
        }
        }
        }
        // 输出
        13
        14
        15
  7. net —WEB处理:
    1. net/url —URL处理:
      1. URL 编/解码:
        package main
        import (
        "fmt"
        "net/url"
        )
        func main()  {
        encoded := url.QueryEscape("http://www.baidu.com")
        fmt.Println(encoded)  // 输出 http%3A%2F%2Fwww.baidu.com
        decoded,_ := url.QueryUnescape(encoded)
        fmt.Println(decoded)  // 输出 http://www.baidu.com
        }
    2. URL 解析:
      package main
      import (
      "fmt"
      "net/url"
      )
      func main()  {
      url := url.URL{}
      r,_ := url.Parse("http://www.baidu.com/a/b?name=xiaoming#title")
      fmt.Println(r.Scheme)  // 输出 http
      fmt.Println(r.Host)  // 输出 www.baidu.com
      fmt.Println(r.Path)  // 输出 /a/b
      fmt.Println(r.RawQuery)  // 输出 name=xiaoming
      fmt.Println(r.Fragment)  // 输出 title
      }
    3. 表单操作:
      package main
      import (
      "fmt"
      "net/url"
      )
      func main()  {
      form := url.Values{}
      // 添加
      form.Add("a","aa")
      form.Add("b","bb")
      form.Add("c","cc")
      // 修改
      form.Set("a","11")
      // 获取
      fmt.Println(form.Get("a"))  // 输出 11
      // 删除
      form.Del("b")
      // 格式化输出
      fmt.Println(form.Encode())  // 输出 a=11&c=cc
      }
    4. net/http —网络请求:
      1. GET 请求:
        package main
        import (
        "fmt"
        "io"
        "io/ioutil"
        "net/http"
        )
        func HTTP_GET(url string) string {
        defer func() {
        if x := recover(); x != nil {
         fmt.Println("从 panic 中恢复:",x)
        }
        }()
        resp, _ := http.Get(url)
        if resp.StatusCode == 200{
        var bodyReader io.ReadCloser = resp.Body
        body, _ := ioutil.ReadAll(bodyReader)
        return string(body)
        }else {
        return ""
        }
        }
        func main() {
        var url string = "http://httpbin.org/get?page=1&limit=2"
        ret := HTTP_GET(url)
        fmt.Println(ret)
        }
        // 输出
        {
        "args": {
        "limit": "2", 
        "page": "1"
        }, 
        "headers": {
        "Accept-Encoding": "gzip", 
        "Host": "httpbin.org", 
        "User-Agent": "Go-http-client/1.1", 
        "X-Amzn-Trace-Id": "Root=1-5eb89b8d-8c8ada7647099878a4a9a21e"
        }, 
        "origin": "110.54.153.6", 
        "url": "http://httpbin.org/get?page=1&limit=2"
        }
      2. POST 请求:
        package main
        import (
        "net/http"
        "fmt"
        "io/ioutil"
        "io"
        "net/url"
        )
        func HTTP_POST(url string,params url.Values) string {
        defer func() {
        if x := recover(); x != nil {
         fmt.Println("从 panic 中恢复:",x)
        }
        }()
        resp, _ := http.PostForm(url, params)
        fmt.Println(resp.StatusCode)  // 输出 200
        if resp.StatusCode == 200{
        var bodyReader io.ReadCloser = resp.Body
        body, _ := ioutil.ReadAll(bodyReader)
        return string(body)
        }else{
        return ""
        }
        }
        func main() {
        var apiURL string = "http://httpbin.org/post?page=1"
        var params url.Values = url.Values{"names[]": []string{"xiaoming", "xiaomei"}}
        params.Set("age", "20")
        ret := HTTP_POST(apiURL,params)
        fmt.Println(ret)
        }
        // 输出
        {
        "args": {
        "page": "1"
        }, 
        "data": "", 
        "files": {}, 
        "form": {
        "age": "20", 
        "names": [
        "xiaoming", 
        "xiaomei"
        ]
        }, 
        "headers": {
        "Accept-Encoding": "gzip", 
        "Content-Length": "35", 
        "Content-Type": "application/x-www-form-urlencoded", 
        "Host": "httpbin.org", 
        "User-Agent": "Go-http-client/1.1", 
        "X-Amzn-Trace-Id": "Root=1-5eb89c05-8b48bc9c15b8d368996b781c"
        }, 
        "json": null, 
        "origin": "110.54.153.6", 
        "url": "http://httpbin.org/post?page=1"
        }
      3. POST 请求(可上传文件):
        package main
        import (
        "bytes"
        "fmt"
        "io"
        "io/ioutil"
        "mime/multipart"
        "net/http"
        "os"
        )
        func HTTP_POST(_url string,data map[string]string,filekey string,path string) string {
        defer func() {
        if x := recover(); x != nil {
         fmt.Println("从 panic 中恢复:",x)
        }
        }()
        bodyBuf := &bytes.Buffer{}
        bodyWriter := multipart.NewWriter(bodyBuf)
        // 拼接请求参数
        for k,v := range data{
        bodyWriter.WriteField(k,v)
        }
        if filekey != "" && path != ""{
        // 设置请求文件
        fileWriter, _ := bodyWriter.CreateFormFile(filekey, path)
        fh, _ := os.Open(path)
        defer fh.Close()
        io.Copy(fileWriter, fh)
        }
        contentType := bodyWriter.FormDataContentType()
        bodyWriter.Close()
        resp, _ := http.Post(_url, contentType, bodyBuf)
        defer resp.Body.Close()
        resp_body, _ := ioutil.ReadAll(resp.Body)
        ret := string(resp_body)
        return ret
        }
        func main() {
        ret := HTTP_POST("http://httpbin.org/post?page=1", map[string]string{"name": "xiaoming","age": "20"},"file","./test.js")
        fmt.Println(ret)
        }
        // 输出
        {
        "args": {
        "page": "1"
        }, 
        "data": "", 
        "files": {
        "file": "class RTCPeerConnectionWrapper {\n    localUserId\n    remoteUserId\n    remoteSdp\n    pc\n    constructor(localUserId, remoteUserId, localStream) {\n        this.localUserId = localUserId;\n        this.remoteUserId = remoteUserId;\n        this.pc = this.create(localStream);\n    }\n    create = function(stream) {\n        var _this = this;\n        var pc = new RTCPeerConnection(null);\n        pc.onicecandidate = function(event) {\n            if (event.candidate) {\n                var message = {\n                    'userId': _this.localUserId,\n                    'msgType': 'candidate',\n                    'id': event.candidate.sdpMid,\n                    'label': event.candidate.sdpMLineIndex,\n                    'candidate': event.candidate.candidate,\n                    'targetUserId': this.remoteUserId\n                };\n                socket.emit('broadcast', JSON.stringify(message));\n                console.log('\u53d1\u9001 candidate: ', message);\n            } else {\n                console.log('candidate \u7ed3\u675f');\n            }\n        }\n        pc.onaddstream = function(event) {\n            console.log('\u6dfb\u52a0\u8fdc\u7a0b\u6d41: ', this.remoteUserId);\n            var video = document.createElement('video');\n            video.srcObject = event.stream;\n            video.autoplay = true;\n            video.muted = true;\n            video.playsinline = true;\n            document.querySelector('#remoteVideos').appendChild(video);\n        }\n        pc.onremovestream = function (event) {\n            console.log('\u8fdc\u7a0b\u6d41\u88ab\u79fb\u9664');\n        };\n        stream.getTracks()\n            .forEach(track => pc.addTrack(track, stream));\n        return pc;\n    }\n    close = function() {\n        this.pc.close();\n    }\n    setRemoteDescription = function(sessionDescription) {\n        if (this.remoteSdp != null) {\n            return\n        }\n        this.remoteSdp = sessionDescription;\n        this.pc.setRemoteDescription(sessionDescription);\n    }\n    addIceCandidate = function(candidate) {\n        this.pc.addIceCandidate(candidate);\n    }\n    createOffer = function() {\n        var _this = this;\n        _this.pc.createOffer()\n            .then(function(offer) {\n                console.log('CreateOfferSdp:', offer);\n                _this.pc.setLocalDescription(offer);\n                var message = {\n                    'userId': _this.localUserId,\n                    'msgType': 'offer',\n                    'sdp': offer.sdp,\n                    'targetUserId': _this.remoteUserId\n                };\n                socket.emit('broadcast', JSON.stringify(message));\n                console.log('Broadcast Offer:', message);\n            })\n            .catch(function(e) {\n                console.log('CreateOffer() error: ', e);\n            })\n    }\n    createAnswer = function() {\n        var _this = this;\n        _this.pc.createAnswer()\n            .then(function(answer) {\n                console.log('CreateAnswerSdp:', answer);\n                _this.pc.setLocalDescription(answer);\n                var message = {\n                    'userId': _this.localUserId,\n                    'msgType': 'answer',\n                    'sdp': answer.sdp,\n                    'targetUserId': _this.remoteUserId\n                };\n                socket.emit('broadcast', JSON.stringify(message));\n                console.log('Broadcast Answer:', message);\n            })\n            .catch(function(e) {\n                console.log('CreateAnswer() error: ', e);\n            })\n    }\n}"
        }, 
        "form": {
        "age": "20", 
        "name": "xiaoming"
        }, 
        "headers": {
        "Accept-Encoding": "gzip", 
        "Content-Length": "3966", 
        "Content-Type": "multipart/form-data; boundary=0d3bf751d44b4008c2ce9cb76fde360b15fa49e3e13bc7399ff097759bf1", 
        "Host": "httpbin.org", 
        "User-Agent": "Go-http-client/1.1", 
        "X-Amzn-Trace-Id": "Root=1-5f67fd2c-2372d58895cecb08315b219c"
        }, 
        "json": null, 
        "origin": "175.176.33.91", 
        "url": "http://httpbin.org/post?page=1"
        }
      4. JSON/XML 请求:
        package main
        import (
        "net/http"
        "fmt"
        "io/ioutil"
        "strings"
        )
        func HTTP_JSON(url string,str string) string {
        defer func() {
        if x := recover(); x != nil {
         fmt.Println("从 panic 中恢复:",x)
        }
        }()
        // 创建客户端实例
        client := &http.Client{}
        // 创建请求实例
        req, _ := http.NewRequest("POST", url, strings.NewReader(str))
        // 增加Header
        req.Header.Add("Content-Type", "application/json")
        req.Header.Add("Content-Encoding", "gzip")
        // 发起请求
        resp, _ := client.Do(req)
        defer func() {
        _ = resp.Body.Close()
        }()
        body,_ := ioutil.ReadAll(resp.Body)
        return string(body)
        }
        func main() {
        var apiURL string = "http://httpbin.org/post?page=1"
        str := `
         {
             "name": "lee",
             "gender": "male"
         }
        `
        ret := HTTP_JSON(apiURL,str)
        fmt.Println(ret)
        }
        // 输出
        {
        "args": {
        "page": "1"
        },
        "data": "\n\t\t\t{\n\t\t\t\t\"name\": \"lee\",\n\t\t\t\t\"gender\": \"male\"\n\t\t\t}\n\t\t",
        "files": {},
        "form": {},
        "headers": {
        "Accept-Encoding": "gzip",
        "Content-Encoding": "gzip",
        "Content-Length": "53",
        "Content-Type": "application/json",
        "Host": "httpbin.org",
        "User-Agent": "Go-http-client/1.1",
        "X-Amzn-Trace-Id": "Root=1-5f127f39-62f99cf6a7d8778c27ac4f0a"
        },
        "json": {
        "gender": "male",
        "name": "lee"
        },
        "origin": "159.138.40.51",
        "url": "http://httpbin.org/post?page=1"
        }
      5. 原生请求:
        package main
        import (
        "net/http"
        "fmt"
        "io/ioutil"
        "net/url"
        "strings"
        )
        func main() {
        _url := "http://httpbin.org/post?page=1"
        var params url.Values = url.Values{}
        params.Set("name", "yujc")
        // 创建客户端实例
        client := &http.Client{}
        // 创建请求实例
        req, _ := http.NewRequest("POST", _url, strings.NewReader(params.Encode()))
        // 增加Header
        req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
        req.Header.Add("Content-Encoding", "gzip")
        // 发起请求
        resp, _ := client.Do(req)
        defer func() {
        _ = resp.Body.Close()
        }()
        body,_ := ioutil.ReadAll(resp.Body)
        //读取响应
        fmt.Println(string(body))
        }
        // 输出
        {
        "args": {
        "page": "1"
        }, 
        "data": "", 
        "files": {}, 
        "form": {
        "name": "yujc"
        }, 
        "headers": {
        "Accept-Encoding": "gzip", 
        "Content-Encoding": "gzip", 
        "Content-Length": "9", 
        "Content-Type": "application/x-www-form-urlencoded", 
        "Host": "httpbin.org", 
        "User-Agent": "Go-http-client/1.1", 
        "X-Amzn-Trace-Id": "Root=1-5eb89d22-c5e0c08be92c50445bf2b13c"
        }, 
        "json": null, 
        "origin": "110.54.153.6", 
        "url": "http://httpbin.org/post?page=1"
        }
      6. 静态文件处理:
        package main
        import "net/http"
        func main() {
        http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("./statics"))))
        http.ListenAndServe(":8080", nil)
        }
    5. net/http/pprof —性能监控:
      package main
      import (
      "net/http"
      _ "net/http/pprof"
      )
      func main(){
      http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
       w.Write([]byte("ok"))
      })
      http.ListenAndServe(":8080", nil)
      }
      // 访问 http://localhost:8080/debug/pprof/
  8. math —数学相关:
    1. 生成随机数:
      package main
      import (
      "fmt"
      "math/rand"
      "time"
      )
      func main() {
      rand.Seed(time.Now().Unix())  // 播种
      fmt.Println(rand.Intn(100))  // 生成
      fmt.Println(rand.Intn(100))
      fmt.Println(rand.Intn(100))
      fmt.Println(rand.Intn(100))
      }
      // 输出
      66
      8
      78
      76
    2. 四舍五入:
      package main
      import (
      "fmt"
      "math"
      )
      func main() {
      fmt.Println(math.Round(3.1415))
      }
      // 输出
      3
  9. os —目录/文件操作:
    1. 目录操作:
      package main
      import "os"
      func main()  {
      os.Mkdir("tmp", 0755)  // 创建目录
      os.MkdirAll("tmp/dir1/dir2", 0755)  // 递归创建
      os.Remove("tmp")  // 删除目录
      os.RemoveAll("tmp")  // 递归删除
      }
    2. 文件操作:
      1. 创建文件:
        package main
        import "os"
        func main()  {
        os.Create("test.txt")
        }
      2. 打开文件:
        package main
        import (
        "fmt"
        "os"
        )
        func main()  {
        fp,_ := os.OpenFile("test.txt",1,0644)
        fmt.Println(fp)  // 输出 &{0xc00001e1e0}
        }
      3. 写文件:
        package main
        import "os"
        func main()  {
        fp,_ := os.OpenFile("test.txt",2,0644)
        defer fp.Close()
        fp.WriteString("Just a test!\r\n")
        }
      4. 读文件:
        package main
        import (
        "fmt"
        "os"
        )
        func main() {
        fl, _ := os.Open("test.txt")
        defer fl.Close()
        buf := make([]byte, 1024)
        for {
        n, _ := fl.Read(buf)
        if 0 == n {
         break
        }
        fmt.Println(string(buf[:n]))
        }
        }
        // 输出
        Just a test!
      5. 删除文件:
        package main
        import "os"
        func main() {
        os.Remove("test.txt")
        }
  10. sort —切片排序:
    1. 正向排序:
      package main
      import (
      "fmt"
      "sort"
      )
      func main() {
      nums := []int{5,2,1,3,4}
      // sort.Float64s(floats)
      // sort.Strings(strings)
      sort.Ints(nums)
      fmt.Println(nums)  // 输出 [1 2 3 4 5]
      // 是否已排序
      fmt.Println(sort.IntsAreSorted(nums))  // 输出 true
      }
    2. 反向排序:
      package main
      import (
      "fmt"
      "sort"
      )
      func main() {
      nums := []int{5,2,1,3,4}
      reverse_nums := sort.Reverse(sort.IntSlice(nums))
      sort.Sort(reverse_nums)
      fmt.Println(nums)  // 输出 [5 4 3 2 1]
      }
    3. 自定义排序:
      package main
      import (
      "fmt"
      "sort"
      )
      func main() {
      arr := []map[string]string{
       {"name":"a","age":"1"},
       {"name":"b","age":"3"},
       {"name":"c","age":"2"},
      }
      sort.SliceStable(arr, func(i, j int) bool {
       return arr[i]["age"] < arr[j]["age"]
      })
      fmt.Println(arr)  // 输出 [map[age:1 name:a] map[age:2 name:c] map[age:3 name:b]]
      }
  11. 切片去重:
    package main
    import "fmt"
    /**
    * 切片去重
    * @param input []interface{}
    * @return result []interface{}
    */
    func ArrayUnique(input []interface{}) []interface{} {
    result := []interface{}{}
    temp := map[interface{}]string{}
    for _, item := range input {
        // 判断 temp[item] 是否已被赋值
        _,exists := temp[item]
        if exists == false{
            temp[item] = ""
            result = append(result,item)
        }
    }
    return result
    }
    func main() {
    arr := []interface{}{1,2,3,5,1,3,6}
    ret := ArrayUnique(arr)
    fmt.Println(ret)
    }
    // 输出
    [1 2 3 5 6]
  12. 判断值是否在切片中:
    package main
    import "fmt"
    /**
    * 判断值是否在切片中
    * @param needle interface{} 值
    * @param haystack []interface{} 切片
    * @return bool true:在切片中;false:不在切片中
    */
    func InArray(needle interface{},haystack []interface{}) bool {
    for _, e := range haystack {
        if e == needle {
            return true
        }
    }
    return false
    }
    func main() {
    arr := []interface{}{1,2,3,4,5}
    var i interface{} = 6
    ret := InArray(i,arr)
    fmt.Println(ret)
    }
    // 输出
    false
  13. 判断字典中的 key 是否已设置(类似于 php 的 isset函数):
    package main
    import "fmt"
    func main() {
    var arr map[string]map[string]int
    arr = map[string]map[string]int{
        "a": {
            "x": 1,
            "y": 2,
        },
        "b": {
            "x": 3,
            "y": 4,
        },
    }
    _,isset1 := arr["a"]  // arr["a"] 存在,返回 true
    _,isset2 := arr["c"]  // arr["c"] 不存在,返回 false
    fmt.Println(isset1,isset2)
    }
    // 输出
    true false
  14. 删除字典中的 key:
    package main
    import "fmt"
    func main() {
    m := map[string]string{
        "a": "aa",
        "b": "bb",
    }
    delete(m,"a")  // 删除 key 为 "a" 的元素
    fmt.Println(m)
    }
    // 输出
    map[b:bb]
  15. 删除切片中指定的元素:
    package main
    import "fmt"
    /**
    * 删除切片中指定的元素
    * @param arr 原切片
    * @param val 要删除的值
    * @return arr 删除后的切片
    */
    func SliceDelete(arr []interface{},val interface{}) []interface{} {
    for k,v := range arr{
        if v == val{
            arr = append(arr[:k],arr[k + 1:]...)
        }
    }
    return arr
    }
    func main() {
    arr := []interface{}{1,2,3,4,5}
    arr = SliceDelete(arr,3)
    fmt.Println(arr)
    }
    // 输出
    [1 2 4 5]
  16. 合并切片:
    package main
    import "fmt"
    func main() {
    a1 := []int{1,2,3}
    a2 := []int{4,5,6}
    a := append(a1,a2...)  // 注意:a2 后面的 ...
    fmt.Println(a)
    }
    // 输出
    [1 2 3 4 5 6]
  17. flag —获取命令行参数:
    -- test.go
    package main
    import (
    "flag"
    "fmt"
    "os"
    )
    func main() {
    a := flag.String("a", "", "参数a")
    b := flag.Bool("b", false, "参数b")
    flag.Parse()
    if *a == "" || *b == false {
        // 打印提示信息
        flag.PrintDefaults()
        os.Exit(1)
    }
    fmt.Println(*a)
    fmt.Println(*b)
    }
    // 运行 go run test.go -a xiaoming -b true
    // 输出
    xiaoming
    true
  18. fmt.printf —格式化输出:
    package main
    import (
    "fmt"
    )
    type myStruct struct {
    x, y int
    }
    func main() {
    // 字符串 - %s
    str := "abc"
    fmt.Printf("%s" + "\n",str)
    // 整型 - %d
    i := 100
    fmt.Printf("%d" + "\n",i)
    // 浮点型 - %f
    f := 3.1415
    fmt.Printf("%.2f" + "\n",f)
    // 布尔型 - %t
    b := true
    fmt.Printf("%t" + "\n",b)
    // 切片/字典/结构体 - %v
    s := []int{1, 2, 3}
    fmt.Printf("%v" + "\n",s)
    m := map[string]string{"a":"aa"}
    fmt.Printf("%v" + "\n",m)
    st := struct {
        name string
        age int
    }{"xiaoming",20}
    fmt.Printf("%v" + "\n",st)
    // 查看变量类型 - %T
    fmt.Printf("%T" + "\n",st)
    }
  19. 编译/运行命令:
    1. 编译:
      go build *.go
      或
      go build .
    2. 运行:
      go run *.go
      或
      go run .
    3. 交叉编译:
      1. linux 系统:
        # linux -> mac
        CGO_ENABLED=0
        GOOS=darwin
        GOARCH=amd64
        go build main.go
        # linux -> windows
        CGO_ENABLED=0
        GOOS=windows
        GOARCH=amd64
        go build main.go
      2. mac 系统:
        # mac -> linux
        CGO_ENABLED=0
        GOOS=linux
        GOARCH=amd64
        go build main.go
        # mac -> windows
        CGO_ENABLED=0
        GOOS=windows
        GOARCH=amd64
        go build main.go
      3. windows 系统:
        # windows -> mac
        SET CGO_ENABLED=0
        SET GOOS=darwin
        SET GOARCH=amd64
        go build main.go
        # windows -> linux
        SET CGO_ENABLED=0
        SET GOOS=linux
        SET GOARCH=amd64
        go build main.go
  20. sync —GO 协程同步:
    1. sync.WaitGroup —计数器(结束单个协程):
      package main
      import (
      "fmt"
      "sync"
      )
      func main() {
      wg := sync.WaitGroup{}
      wg.Add(3)
      for i := 0; i < 3; i++ {
       go func(i int,wg *sync.WaitGroup) {
           fmt.Println(i)
           wg.Done()
       }(i,&wg)
      }
      wg.Wait()
      }
      // 输出
      2
      0
      1
    2. sync.Mutex —线程锁:
      package main
      import (
      "fmt"
      "sync"
      "time"
      )
      func main() {
      wg := sync.Mutex{}
      for i := 0; i < 3; i++ {
       go func(i int,wg *sync.Mutex) {
           wg.Lock()
           defer wg.Unlock()
           fmt.Println(i)
       }(i,&wg)
      }
      select {
       case <- time.After(time.Second):  // 1秒超时
           return
      }
      }
      // 输出
      0
      2
      1
  21. go routine —协程:
    1. range + close组合 —单 channel(结束所有协程):
      package main
      import (
      "fmt"
      )
      func main() {
      c := make(chan int)
      for j := 0;j < 3;j ++ {
       go func() {
           for i := 0;i < 3;i ++ {
               c <- i  // todo: 在协程函数中 push数据到 channel 中
           }
           close(c)
       }()
      }
      for i := range c{
       fmt.Println(i)  // todo: 在外部消耗 channel
      }
      }
      // 输出
      0
      1
      0
      0
      1
      2
    2. select —多 channel(结束所有协程):
      package main
      import (
      "fmt"
      )
      func main() {
      run := make(chan int)
      quit := make(chan string)
      for i := 0;i < 10;i ++{
       go func(i int) {
           run <- i
           if i == 1{
               quit <- "yes, I quited!"
           }
       }(i)
      }
      for{
       select {
       case <- run:
           fmt.Println("running")  // todo: 在外部消耗 channel
       case <- quit:
           fmt.Println("quited")
           return
           // case <- time.After(5 * time.Second):  // 超时
           // return
       }
      }
      }
      // 输出
      running
      running
      running
      quited
    3. chan —多线程阻塞:
      package main
      import "fmt"
      func main() {
      c := make(chan int)  // 创建
      for i := 0;i < 10;i ++{
       go func(i int) {
           fmt.Println(i)
       }(i)
      }
      <- c  // 消耗
      }
      // 输出
      1
      2
      3
      ...
    4. chan —多线程阻塞(指定个数,同 sync.WaitGroup):
      package main
      import (
      "fmt"
      )
      func main() {
      c := make(chan int)
      for i := 0; i < 10; i++ {
       go func(i int){
           fmt.Println("你好, 世界")
           c <- i
       }(i)
      }
      for i := 0; i < 10; i++ {  // 等待 10个后台线程完成
       <-c
      }
      }
      // 输出
      4
      9
      5
      6
      7
      8
      2
      1
      0
      3
    5. slice -消耗切片中的任务(指定 go程数量,回调函数):
      package main
      import (
      "fmt"
      "math"
      "sync"
      )
      /*
      * 开 go 程,消耗切片中的任务
      * @param s 切片
      * @param num go 程数量
      * @param f 回调函数
      */
      func SliceGo(s []interface{}, num int,f func(v interface{}))  {
      _len := len(s)
      if _len < num{
       num = _len
      }
      wg := sync.WaitGroup{}
      wg.Add(num)
      one := math.Floor(float64(_len / num))
      for i := 0;i < num;i ++{
       start := i * int(one)
       one_s := []interface{}{}
       if i < num - 1{
           end := (i + 1) * int(one)
           one_s = s[start:end]
       }else {
           one_s = s[start:]
       }
       go func() {
           for _,v := range one_s{
               f(v)
           }
           wg.Done()
       }()
      }
      wg.Wait()
      }
      func main() {
      num := 6
      s := []interface{}{1,2,3,4,5}
      // 调用
      SliceGo(s,num, func(v interface{}) {
       fmt.Println(v)
      })
      }
      // 输出
      5
      2
      3
      4
      1
文档更新时间: 2020-10-23 09:26   作者:lee