Golang内置常用包

strings 字符串函数

  • Contains(s, substr string) bool
    字符串s是否包含字符串substr,包含返回true
  • Split(s, sep string) []string
    将字符串s按照分隔符sep分隔为slice
  • Join(a []string, sep string) string
    字符串拼接,把slice a通过sep链接起
  • Trim(s string, cutset string) string
    在s字符串的头部和尾部去除cutset指定的字符串
  • Replace(s, old, new string, n int) string
    在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换,等于0不替换
  • Repeat(s string, count int) string
    重复s字符串count次,最后返回重复的字符串
  • Index(s, substr string) int
    在字符串s中查找sep所在的位置,返回位置值,找不到返回-1。注意返回0表示首位置

strconv 字符串转换

Append 系列函数

将整数等转换为字符串后,添加到现有的字节数组中。

package main

import (
    "fmt"
    "strconv"
)

func main()  {
    str := make([]byte, 0, 10)
    str = strconv.AppendInt(str, -1, 10)
    str = strconv.AppendUint(str, 1, 10) //无符号
    fmt.Println(string(str))
    str = strconv.AppendFloat(str, 3.14159, 'f', 2, 32)
    fmt.Println(string(str))
    str = strconv.AppendFloat(str, 30.14159, 'e', 3, 64)
    fmt.Println(string(str))
    str = strconv.AppendBool(str, true)
    fmt.Println(string(str))
    str = strconv.AppendQuote(str, "hello")
    fmt.Println(string(str))
    str = strconv.AppendQuoteRune(str, 97) //字符a对应的ascii码
    fmt.Println(string(str))

}

输出:

-11
-113.14
-113.143.014e+01
-113.143.014e+01true
-113.143.014e+01true"hello"
-113.143.014e+01true"hello"'a'

注:
1、strconv.AppendInt(dst []byte, i int64, base int)的第三个参数是进制,这里写的 10 代表10进制。
2、strconv.AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int)fmt是格式标记(b、e、E、f、g、G);prec代表精度(数字部分的长度,不包括指数部分);bitSize指定浮点类型(32:float32、64:float64)。
格式标记:

// 'b' (-ddddp±ddd,二进制指数)
// 'e' (-d.dddde±dd,十进制指数)
// 'E' (-d.ddddE±dd,十进制指数)
// 'f' (-ddd.dddd,没有指数)
// 'g' ('e':大指数,'f':其它情况)
// 'G' ('E':大指数,'f':其它情况)

// 如果格式标记为 'e','E'和'f',则 prec 表示小数点后的数字位数
// 如果格式标记为 'g','G',则 prec 表示总的数字位数(整数部分+小数部分)

3、strconv.AppendQuote(dst []byte, s string) []byte 将字符串 s 转换为"双引号"引起来的字符串,并将结果追加到 dst 的尾部,返回追加后的 []byte。其中的特殊字符将被转换为"转义字符"。

Format 系列函数

把其他类型的转换为字符串。

package main

import (
    "fmt"
    "strconv"
)

func main()  {
    fmt.Println(strconv.FormatBool(true))
    fmt.Println(strconv.FormatInt(1, 10))
    fmt.Println(strconv.FormatUint(1, 10))
    fmt.Println(strconv.FormatFloat(3.14159, 'f', 2, 32))
}

输出:

true
1
1
3.14

Parse 系列函数

将字符串转换为 bool float int uint类型的值,err指定是否转换成功。

package main

import (
    "fmt"
    "strconv"
)

func main()  {
    fmt.Println(strconv.ParseBool("true"))
    fmt.Println(strconv.ParseInt("100", 10, 0))
    fmt.Println(strconv.Atoi("100")) // 通常使用这个函数,而不使用 ParseInt
    fmt.Println(strconv.ParseUint("100", 10, 0))
    fmt.Println(strconv.ParseFloat("3.14159", 32))
}

输出:

true <nil>
100 <nil>
100 <nil>
100 <nil>
3.141590118408203 <nil>

注:
1、strconv.ParseInt(s string, base int, bitSize int)的第三个参数bitSize是返回结果的bit大小,也就是int8 int16 int32 int64。如果给0,则使用默认值strconv.IntSize,64位机器大小是64。

Quote 系列函数

1、strconv.Quote(s string) string将字符串 s 转换为"双引号"引起来的字符串,其中的特殊字符将被转换为"转义字符","不可显示的字符"将被转换为"转义字符"。
2、strconv.QuoteToASCII(s string) string 将字符串 s 转换为""引起来的 ASCII 字符串, "非 ASCII 字符"和"特殊字符"将被转换为"转义字符"。
3、strconv.QuoteRune(r rune) string 将 Unicode 字符转换为“单引号”引起来的字符串,“特殊字符”将被转换为“转义字符”。

package main

import (
    "fmt"
    "strconv"
)

func main()  {
    fmt.Println(strconv.Quote(`hello go 语言\n`))
    fmt.Println(strconv.Quote("hello go 语言\n"))
    fmt.Println(strconv.QuoteToASCII(`hello go 语言\n`))
    fmt.Println(strconv.QuoteRune(97))
    fmt.Println(strconv.QuoteRuneToASCII(97))
}

输出:

扫描二维码关注公众号,回复: 6940114 查看本文章
"hello go 语言\\n"
"hello go 语言\n"
"hello go \u8bed\u8a00\\n"
'a'
'a'

encoding

encoding/json

  • json.Marshal(v interface{}) ([]byte, error) 生成JSON
  • json.Unmarshal(data []byte, v interface{}) error 解析JSON到interface

解析JSON

package main

import (
    "encoding/json"
    "fmt"
)

type Employee struct {
    FirstName string `json:"firstName"`
    LastName string `json:"lastName"`
}

type EmployeeSlice struct {
    Employees []Employee `json:"employees"`
}

func main()  {
    str := `{"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"}]}`
    var res EmployeeSlice
    json.Unmarshal([]byte(str), &res)
    fmt.Println(res)
    fmt.Println(res.Employees[0].FirstName)
}

输出:

[{Bill Gates} {George Bush}]}
Bill

生成JSON:

package main

import (
    "encoding/json"
    "fmt"
)

type Employee struct {
    FirstName string `json:"firstName"`
    LastName string `json:"lastName"`
}

type EmployeeSlice struct {
    Employees []Employee `json:"employees"`
}

func main()  {
    data := EmployeeSlice{[]Employee{
        {FirstName:"Bill", LastName:"Gates"},
        {FirstName:"George", LastName:"Bush"},
    }}
    res,_ := json.Marshal(data)
    fmt.Println(string(res))
}

输出:

{"employees":[{"firstName":"Bill","lastName":"Gates"},{"firstName":"George","lastName":"Bush"}]}

crypto

md5

package main

import (
    "crypto/md5"
    //"io"
    "fmt"
    "encoding/hex"
)

func main(){
    h := md5.New()
    //io.WriteString(h, "123456")
    h.Write([]byte("123456"))
    cipherStr := h.Sum(nil)
    fmt.Println(cipherStr) //一个128bit的16字节byte数组
    fmt.Println(hex.EncodeToString(cipherStr)) // 输出加密结果 
}

运行输出:

[225 10 220 57 73 186 89 171 190 86 224 87 242 15 136 62]
e10adc3949ba59abbe56e057f20f883e

使用io.WriteString(h, "123456")h.Write([]byte("123456"))作用相同,可以多次Write,会把字符串追加到前一次的末尾。

除了md5,还有sha1sha256,使用方法是类似的:

//import "crypto/sha256"
h := sha256.New()
io.WriteString(h, "123456")
fmt.Printf("%x", h.Sum(nil))

//import "crypto/sha1"
h := sha1.New()
io.WriteString(h, "123456")
fmt.Printf("%x", h.Sum(nil))

base64

package main

import (
    "encoding/base64"
    "fmt"
)

// 编码
func base64Encode(str []byte) []byte {
    return []byte(base64.StdEncoding.EncodeToString(str))
}

// 解码
func base64Decode(str []byte) ([]byte, error){
    return base64.StdEncoding.DecodeString(string(str))
}

func main(){
    str := "hello"
    enc_str := base64Encode([]byte(str))
    fmt.Println(enc_str)
    fmt.Println(string(enc_str))

    dec_str,err := base64Decode(enc_str)
    if(err != nil){
        fmt.Println(err.Error())
    }

    fmt.Println(dec_str)
    fmt.Println(string(dec_str))
}

输出:

[97 71 86 115 98 71 56 61]
aGVsbG8=
[104 101 108 108 111]
hello

AES

net

net/url

net/http

net/http已经很好的支持了常见的GET、POST请求。

get请求

package main

import (
    "net/http"
    "fmt"
    "io/ioutil"
    "io"
)

func main() {
    var url string = "http://httpbin.org/get?page=1&limit=2"
    resp, err := http.Get(url)
    if (err != nil) {
        fmt.Println(err.Error())
    }

    fmt.Println(resp.Status)     //200 ok
    fmt.Println(resp.StatusCode) //200

    var bodyReader io.ReadCloser = resp.Body //返回的是io.Reader
    body, _ := ioutil.ReadAll(bodyReader)
    fmt.Println(string(body))
}

输出:

200 OK
200
{
  "args": {
    "limit": "2", 
    "page": "1"
  }, 
  "headers": {
    "Accept-Encoding": "gzip", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "Go-http-client/1.1"
  }, 
  "origin": "221.217.54.202", 
  "url": "http://httpbin.org/get?page=1&limit=2"
}

post表单请求

post表单请求使用http.PostForm()。除了需要额外的参数外,其它的和get请求一样。

package main

import (
    "net/http"
    "fmt"
    "io/ioutil"
    "io"
    "net/url"
)

func main() {
    var apiURL string = "http://httpbin.org/post?page=1"
    var params url.Values = url.Values{"names": []string{"yjc", "yjc1"}}
    params.Set("age", "20")
    resp, err := http.PostForm(apiURL, params)
    if (err != nil) {
        fmt.Println(err.Error())
    }

    fmt.Println(resp.Status)     //200 ok
    fmt.Println(resp.StatusCode) //200

    var bodyReader io.ReadCloser = resp.Body //返回的是io.Reader
    body, _ := ioutil.ReadAll(bodyReader)
    fmt.Println(string(body))
}

输出:

200 OK
200
{
  "args": {
    "page": "1"
  }, 
  "data": "", 
  "files": {}, 
  "form": {
    "age": "20", 
    "names": [
      "yjc", 
      "yjc1"
    ]
  }, 
  "headers": {
    "Accept-Encoding": "gzip", 
    "Connection": "close", 
    "Content-Length": "27", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Go-http-client/1.1"
  }, 
  "json": null, 
  "origin": "221.217.54.202", 
  "url": "http://httpbin.org/post?page=1"
}

封装

package tool

import (
    "io/ioutil"
    "net/http"
    "net/url"
    "fmt"
)

// get 网络请求
func Get(apiURL string, params url.Values) (rs []byte, err error) {
    var Url *url.URL
    Url, err = url.Parse(apiURL)
    if err != nil {
        fmt.Printf("解析url错误:\r\n%v", err)
        return nil, err
    }
    //如果参数中有中文参数,这个方法会进行URLEncode
    Url.RawQuery = params.Encode()
    resp, err := http.Get(Url.String())
    if err != nil {
        fmt.Println("err:", err)
        return nil, err
    }
    defer resp.Body.Close()
    return ioutil.ReadAll(resp.Body)
}

// post 网络请求 ,params 是url.Values类型
func Post(apiURL string, params url.Values) (rs []byte, err error) {
    resp, err := http.PostForm(apiURL, params)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    return ioutil.ReadAll(resp.Body)
}

net/http/pprof

该包来做代码的性能监控。使用示例:

package main

import (
    "net/http"
    _ "net/http/pprof"
)

func main(){
    //提供给负载均衡探活以及pprof调试
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("ok"))
    })

    http.ListenAndServe(":10000", nil)
}

运行之后,在浏览器打开 http://127.0.0.1:10000/debug/pprof/就能看到监控的一些信息了。生产环境一般不会按上面那么写,一般都是开个协程:

go http.ListenAndServe(":10000", nil)

如何启动 PProf 可视化界面?

需要graphviz支持,可以到 http://www.graphviz.org/download/下载,并把bin加入到环境变量。Mac可以使用brew安装

下面以profile( CPU profile)为例:

方法一:

go tool pprof -http=:8080 http://localhost:10000/debug/pprof/profile

方法二:

go tool pprof http://localhost:10000/debug/pprof/profile

然后在交互式命令行输入web即可跳转到默认浏览器。(本机测试失败,打开了Sublime text)

参考:Golang pprof详解
https://studygolang.com/articles/14519

os

文件操作的大多数函数都是在os包里面。

目录操作:

  • func Mkdir(name string, perm FileMode) error
    创建名称为name的目录,权限设置是perm,例如0777。
  • func MkdirAll(path string, perm FileMode) error
    根据path创建多级子目录。
  • func Remove(name string) error
    删除名称为name的目录,当目录下有文件或者其他目录时会出错。
  • func RemoveAll(path string) error
    根据path删除多级子目录,如果path是单个名称,那么该目录下的子目录全部删除。

示例:

package main

import (
    "os"
    "fmt"
)

func main()  {
    os.Mkdir("tmp", 0755)
    os.MkdirAll("tmp/test/test2", 0755)
    err := os.Remove("tmp")
    if err != nil{
        fmt.Println(err)
    }
    os.RemoveAll("tmp")
}

运行输出:

remove tmp: The directory is not empty.

文件操作:

  • func Create(name string) (file *File, err Error)
    根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。
  • func NewFile(fd uintptr, name string) *File
    根据文件描述符创建相应的文件,返回一个文件对象。

  • func Open(name string) (file *File, err Error)
    该方法打开一个名称为name的文件,但是是只读方式,内部实现其实调用了
    OpenFile。
  • func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
    打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限
  • func (file *File) Write(b []byte) (n int, err Error)
    写入byte类型的信息到文件
  • func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
    在指定位置开始写入byte类型的信息
  • func (file *File) WriteString(s string) (ret int, err Error)
    写入string信息到文件
  • func (file *File) Read(b []byte) (n int, err Error)
    读取数据到b中
  • func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
    从off开始读取数据到b中
  • func Remove(name string) Error
    调用该函数就可以删除文件名为name的文件。删除文件和删除文件夹是同一个函数。

io/ioutil

ioutil包封装了一些实用的 I/O 函数,提供给外部使用的一共有1个变量,7个方法。

  • func ReadFile(filename string) ([]byte, error)
    ReadFile读取文件中的所有数据,返回读取的内容和遇到的错误。
  • func WriteFile(filename string, data []byte, perm os.FileMode) error
    WriteFile向文件写入数据,如果之前有数据则会将原来的进行清空,如果文件不存在则会以指定的权限创建该文件。

  • func ReadDir(dirname string) ([]os.FileInfo, error)
    ReadDir读取指定目录中的所有目录和文件(不包括子目录)。返回读取的文件信息列表和遇到的错误,列表是经过排序的。

  • func TempFile(dir, prefix string) (f *os.File, err error)
    TempFile在dir目录中创建一个以prefix为前缀的临时文件,并将其以读写模式打开。返回创建的文件对象和遇到的错误信息。如果dir为空,则在默认的临时目录中创建文件(参见os.TimeDir),多次调用会创建不同的临时文件,调用者可以通过f.Name()获取文件的完整路径。调用本函数所创建的临时文件,应该由调用者自己删除。
  • func TempDir(dir, prefix string) (name string, err error)
    TempDir功能是创建临时目录(其他功能和TempFile一样),返回创建的完整的目录和遇到的错误信息。

  • func ReadAll(r io.Reader) ([]byte, error)
    ReadFile读取文件中的所有数据,返回读取的数据和遇到的错误。如果读取成功,则err返回nil,而不是EOF。该方法实现了io.Reader接口的使用。

  • func NopCloser(r io.Reader) io.ReadCloser
    NopCloser将r包装为一个ReadCloser类型,但Close方法不做任何事情。

io

io包是为 IO 原语(I/O primitives)提供基本的接口。

golang的io包 - 刘地的个人空间 - 开源中国
https://my.oschina.net/liudiwu/blog/305023

flag

用于获取命令行参数。

示例:

package main

import (
    "flag"
    "fmt"
)

func main() {
    backup_dir := flag.String("b", "/home/default_dir", "backup path")
    debug_mode := flag.Bool("d", false, "debug mode")

    flag.Parse()

    fmt.Println("backup_dir: ", *backup_dir)
    fmt.Println("debug_mode: ", *debug_mode)
}

golang之flag.String - hezhixiong - 博客园
http://www.cnblogs.com/hezhixiong/p/4659477.html

sync

sync.WaitGroup

package main

import (
    "fmt"
    "time"
)

func main(){
    for i := 0; i < 100 ; i++{
        go fmt.Println(i)
    }
    time.Sleep(time.Second)
}

上面主线程为了等待goroutine都运行完毕,不得不在程序的末尾使用time.Sleep() 来睡眠一段时间,等待其他线程充分运行。但大部分时候我们都无法预知for循环内代码运行时间的长短。这时候就不能使用time.Sleep() 来完成等待操作了。

对于这种情况,go语言中有一个其他的工具sync.WaitGroup 能更加方便的帮助我们达到这个目的。WaitGroup 对象内部有一个计数器,最初从0开始,它有三个方法:Add(), Done(), Wait() 用来控制计数器的数量。Add(n) 把计数器设置为nDone() 每次把计数器-1wait() 会阻塞代码的运行,直到计数器地值减为0

使用WaitGroup 将上述代码可以修改为:

func main() {
    wg := sync.WaitGroup{}
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go func(i int) {
            fmt.Println(i)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

详见:Golang sync.WaitGroup的用法
https://studygolang.com/articles/12972?fr=sidebar

runtime

runtime/debug

用于:

  • 强制进行垃圾回收
  • 设置垃圾回收的目标百分比
  • 设置被单个go协程调用栈可使用的内存最大值
  • 设置go程序可以使用的最大操作系统线程数
  • 设置程序请求运行是只触发panic,而不崩溃
  • 垃圾收集信息的写入stats中
  • 将内存分配堆和其中对象的描述写入文件中
  • 获取go协程调用栈踪迹
  • 将堆栈踪迹打印到标准错误

详见:go-runtime/debug
https://www.jianshu.com/p/0b3d11f7af57

猜你喜欢

转载自www.cnblogs.com/52fhy/p/11295090.html
今日推荐