strings 字符串函数
Contains(s, substr string) bool
字符串s是否包含字符串substr,包含返回trueSplit(s, sep string) []string
将字符串s按照分隔符sep分隔为sliceJoin(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))
}
输出:
"hello go 语言\\n"
"hello go 语言\n"
"hello go \u8bed\u8a00\\n"
'a'
'a'
encoding
encoding/json
json.Marshal(v interface{}) ([]byte, error)
生成JSONjson.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
,还有sha1
、sha256
,使用方法是类似的:
//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)
把计数器设置为n
,Done()
每次把计数器-1
,wait()
会阻塞代码的运行,直到计数器地值减为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