Go 语言常用包笔记
bufio
包
实现了带缓存的 I/O 操作。
Read 相关函数
NewReaderSize、NewReader
1 | func NewReaderSize(rd io.Reader, size int) *Reader |
NewReaderSize 将 rd 封装成一个带缓存的 bufio.Reader 对象,缓存大小由 size 指定(如果小于 16 则会被设置为 16)。
如果 rd 的基类型就是有足够缓存的 bufio.Reader 类型,则直接将 rd 转换为基类型返回。
1 | func NewReader(rd io.Reader) *Reader |
NewReader 相当于 NewReaderSize(rd, 4096)。
bufio.Reader 实现了如下接口:
1 | io.Reader |
Peek
1 | func (b *Reader) Peek(n int) ([]byte, error) |
Peek 返回缓存的一个切片,该切片引用缓存中前 n 个字节的数据,该操作不会将数据读出,只是引用,引用的数据在下一次读取操作之前是有效的。如果切片长度小于 n,则返回一个错误信息说明原因。如果 n 大于缓存的总大小,则返回 ErrBufferFull。
Read
1 | func (b *Reader) Read(p []byte) (n int, err error) |
Read 从 b 中读出数据到 p 中,返回读出的字节数和遇到的错误。
如果缓存不为空,则只能读出缓存中的数据,不会从底层 io.Reader中提取数据,如果缓存为空,则:
1、len(p) >= 缓存大小,则跳过缓存,直接从底层 io.Reader 中读出到 p 中。
2、len(p) < 缓存大小,则先将数据从底层 io.Reader 中读取到缓存中,再从缓存读取到 p 中。
Buffered
1 | func (b *Reader) Buffered() int |
Buffered 返回缓存中未读取的数据的长度。
Discard
1 | func (b *Reader) Discard(n int) (discarded int, err error) |
Discard 跳过后续的 n 个字节的数据,返回跳过的字节数。
如果结果小于 n,将返回错误信息。
如果 n 小于缓存中的数据长度,则不会从底层提取数据。
ReadSlice
1 | func (b *Reader) ReadSlice(delim byte) (line []byte, err error) |
ReadSlice 在 b 中查找 delim 并返回 delim 及其之前的所有数据。
该操作会读出数据,返回的切片是已读出的数据的引用,切片中的数据在下一次读取操作之前是有效的。
如果找到 delim,则返回查找结果,err 返回 nil。
如果未找到 delim,则:
1、缓存不满,则将缓存填满后再次查找。
2、缓存是满的,则返回整个缓存,err 返回 ErrBufferFull。
如果未找到 delim 且遇到错误(通常是 io.EOF),则返回缓存中的所有数据和遇到的错误。
因为返回的数据有可能被下一次的读写操作修改,所以大多数操作应该使用 ReadBytes 或 ReadString,它们返回的是数据的拷贝。
ReadLine
1 | func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) |
ReadBytes、ReadString
1 | func (b *Reader) ReadBytes(delim byte) (line []byte, err error) |
ReadBytes 功能同 ReadSlice,只不过返回的是缓存的拷贝。
1 | func (b *Reader) ReadString(delim byte) (line string, err error) |
ReadString 功能同 ReadBytes,只不过返回的是字符串。
Reset
1 | func (b *Reader) Reset(r io.Reader) |
Reset 将 b 的底层 Reader 重新指定为 r,同时丢弃缓存中的所有数据,复位
所有标记和错误信息。 bufio.Reader。
示例1:Peek、Read、Discard、Buffered
1 | func main() { |
示例2:ReadLine
1 | func main() { |
示例3:ReadSlice
1 | func main() { |
Write 相关函数
NewWriterSize、NewWriter
1 | func NewWriterSize(wr io.Writer, size int) *Writer |
1 | func NewWriter(wr io.Writer) *Writer |
bufio.Writer 实现了如下接口:
1 | io.Writer |
WriteString
1 | func (b *Writer) WriteString(s string) (int, error) |
WriteString 功能同 Write,只不过写入的是字符串。
WriteRune
1 | func (b *Writer) WriteRune(r rune) (size int, err error) |
WriteRune 向 b 写入 r 的 UTF-8 编码,返回 r 的编码长度。
Flush
1 | func (b *Writer) Flush() error |
Flush 将缓存中的数据提交到底层的 io.Writer 中。
Available
1 | func (b *Writer) Available() int |
Available 返回缓存中未使用的空间的长度。
Buffered
1 | func (b *Writer) Buffered() int |
Buffered 返回缓存中未提交的数据的长度。
Reset
1 | func (b *Writer) Reset(w io.Writer) |
Reset 将 b 的底层 Writer 重新指定为 w,同时丢弃缓存中的所有数据,复位所有标记和错误信息。相当于创建了一个新的 bufio.Writer。
示例1:Available、Buffered、WriteString、Flush
1 | func main() { |
type ReadWriter
ReadWriter 集成了 bufio.Reader 和 bufio.Writer。
1 | type ReadWriter struct { |
1 | func NewReadWriter(r *Reader, w *Writer) *ReadWriter |
NewReadWriter 将 r 和 w 封装成一个 bufio.ReadWriter 对象。
type Scanner
1 | type Scanner struct { ... } |
1 | func NewScanner(r io.Reader) *Scanner |
NewScanner 创建一个 Scanner 来扫描 r,默认匹配函数为 ScanLines。
1 | func (s *Scanner) Buffer(buf []byte, max int) |
Buffer 用于设置自定义缓存及其可扩展范围,如果 max 小于 len(buf),则 buf 的尺寸将固定不可调。Buffer 必须在第一次 Scan 之前设置,否则会引发 panic。
默认情况下,Scanner 会使用一个 4096 - bufio.MaxScanTokenSize 大小的内部缓存。
1 | func (s *Scanner) Split(split SplitFunc) |
Split 用于设置“匹配函数”,这个函数必须在调用 Scan 前执行。
type SplitFunc
1 | type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error) |
1 | func (s *Scanner) Scan() bool |
Scan 开始一次扫描过程,如果匹配成功,可以通过 Bytes() 或 Text() 方法取出结果,如果遇到错误,则终止扫描,并返回 false。
1 | func (s *Scanner) Bytes() []byte |
Bytes 将最后一次扫描出的“匹配部分”作为一个切片引用返回,下一次的 Scan 操作会覆盖本次引用的内容。
1 | func (s *Scanner) Text() string |
Text 将最后一次扫描出的“匹配部分”作为字符串返回(返回副本)。
1 | func (s *Scanner) Err() error |
Err 返回扫描过程中遇到的非 EOF 错误,供用户调用,以便获取错误信息。
1 | func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) |
ScanBytes 是一个“匹配函数”用来找出 data 中的单个字节并返回。
1 | func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) |
ScanRunes 是一个“匹配函数”,用来找出 data 中单个 UTF8 字符的编码。如果 UTF8 编码错误,则 token 会返回 “\xef\xbf\xbd”(即:U+FFFD),但只消耗 data 中的一个字节。
这使得调用者无法区分“真正的U+FFFD字符”和“解码错误的返回值”。
1 | func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) |
ScanLines 是一个“匹配函数”,用来找出 data 中的单行数据并返回(包括空行)。
行尾标记可以是 \n 或 \r\n(返回值不包含行尾标记)
1 | func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) |
ScanWords 是一个“匹配函数”,用来找出 data 中以空白字符分隔的单词。
空白字符由 unicode.IsSpace 定义。
示例1:扫描
1 | func main() { |
示例2:待检查扫描
1 | func main() { |
bytes
包
对于传入 []byte 的函数,都不会修改传入的参数,返回值要么是参数的副本,要么是参数的切片。
转换
将s中所有字符修改为大写(小写、标题)格式返回
1 | func ToUpper(s []byte) []byte |
使用指定的映射表将 s 中的所有字符修改为大写(小写、标题)格式返回
1 | func ToUpperSpecial(_case unicode.SpecialCase, s []byte) []byte |
将 s 中的所有单词的首字符修改为 Title 格式返回
1 | func Title(s []byte) []byte |
BUG: 不能很好的处理以 Unicode 标点符号分隔的单词
比较
比较两个[]byte的字典顺序
nil 参数相当于空[]byte
1 | func Compare(a, b []byte) int |
a < b 返回 -1
a == b 返回 0
a > b 返回 1
判断a、b是否相等
nil 相当于空[]byte
1 | func Equal(a, b []byte) bool |
判断s,t是否相似
忽略大写、小写、标题三种格式的区别。
参考 unicode.SimpleFold
函数
1 | func EqualFold(s, t []byte) bool |
清理
去掉 s 左右两边包含在cutset中的字符(返回s的切片)
1 | func Trim(s []byte, cutset string) []byte |
去掉s两边符合f要求的字符(返回s的切片)
1 | func TrimFunc(s []byte, f func(r rune) bool) []byte |
去掉s两边的空白(unicode.IsSpace)(返回s的切片)
1 | func TrimSpace(s []byte) []byte |
去掉 s 的前缀 prefix(后缀 suffix)(返回 s 的切片)
1 | func TrimPrefix(s, prefix []byte) []byte |
拆合
Split按seq分割
Split 以 sep 为分隔符将 s 切分成多个子串,结果不包含分隔符。
如果 sep 为空,则将 s 切分成 Unicode 字符列表。
SplitN 可以指定切分次数 n,超出 n 的部分将不进行切分。
1 | func Split(s, sep []byte) [][]byte |
SplitAfter
功能同 Split,只不过结果包含分隔符(在各个子串尾部)。
1 | func SplitAfter(s, sep []byte) [][]byte |
Fields 空白符分割
以连续空白为分隔符将 s 切分成多个子串,结果不包含分隔符。
1 | func Fields(s []byte) [][]byte |
以符合 f 的字符为分隔符将 s 切分成多个子串,结果不包含分隔符
1 | func FieldsFunc(s []byte, f func(rune) bool) [][]byte |
Join,sep为连接符
1 | func Join(s [][]byte, sep []byte) []byte |
把子串b重复count次吼返回
1 | func Repeat(b []byte, count int) []byte |
eg.
1 | func main() { |
子串
判断前缀、后缀
1 | func HasPrefix(s, prefix []byte) bool |
是否包含子串subslice 或字符r
1 | func Contains(b, subslice []byte) bool |
是否包含chars中任一字符
1 | func ContainsAny(b []byte, chars string) bool |
查找子串seq(字节c、字符r)在s中第一次出现的位置
找不到则返回-1
1 | func Index(s, sep []byte) int |
查找chars中任一字符在s中第一次出现的位置
找不到则返回-1
1 | func IndexAny(s []byte, chars string) int |
查找符合f的字符在s中第一次出现的位置
找不到则返回-1
1 | func IndexFunc(s []byte, f func(r rune) bool) int |
功能同上,只不过查找最后一次出现的位置
1 | func LastIndex(s, sep []byte) int |
获取seq在s中出现的次数(不重叠)
1 | func Count(s, sep []byte) int |
替换
s中前n个old替换为new,n<0则替换全部
1 | func Replace(s, old, new []byte, n int) []byte |
将 s 中的字符替换为 mapping(r) 的返回值
如果 mapping 返回负值,则丢弃该字符
1 | func Map(mapping func(r rune) rune, s []byte) []byte |
将s转换为[]rune类型返回
1 | func Runes(s []byte) []rune |
type
type Reader
1 | type Reader struct { ... } |
将 b 包装成 bytes.Reader 对象。
1 | func NewReader(b []byte) *Reader |
bytes.Reader 实现了如下接口:
1 | io.ReadSeeker |
返回未读取部分的数据长度:
1 | func (r *Reader) Len() int |
返回底层数据的总长度,方便ReadAt使用,返回值永远不变:
1 | func (r *Reader) Size() int64 |
将底层数据切换为 b,同时复位所有标记(读取位置等信息)
1 | func (r *Reader) Reset(b []byte) |
eg.
1 | func main() { |
type Buffer
1 | type Buffer struct { ... } |
将 buf 包装成 bytes.Buffer 对象:
1 | func NewBuffer(buf []byte) *Buffer |
将 s 转换为 []byte 后,包装成 bytes.Buffer 对象:
1 | func NewBufferString(s string) *Buffer |
Buffer 本身就是一个缓存(内存块),没有底层数据,缓存的容量会根据需要自动调整。大多数情况下,使用 new(Buffer) 就足以初始化一个 Buffer 了。
bytes.Buffer 实现了如下接口:
1 | io.ReadWriter |
未读取部分的数据长度:
1 | func (b *Buffer) Len() int |
缓存的容量:
1 | func (b *Buffer) Cap() int |
读取前 n 字节的数据并以切片形式返回,如果数据长度小于 n,则全部读取。
切片只在下一次读写操作前合法。
1 | func (b *Buffer) Next(n int) []byte |
读取第一个 delim 及其之前的内容,返回遇到的错误(一般是 io.EOF):
1 | func (b *Buffer) ReadBytes(delim byte) (line []byte, err error) |
写入 r 的 UTF-8 编码,返回写入的字节数和 nil。
保留 err 是为了匹配 bufio.Writer 的 WriteRune 方法。
1 | func (b *Buffer) WriteRune(r rune) (n int, err error) |
写入 s,返回写入的字节数和 nil:
1 | func (b *Buffer) WriteString(s string) (n int, err error) |
引用未读取部分的数据切片(不移动读取位置):
1 | func (b *Buffer) Bytes() []byte |
返回未读取部分的数据字符串(不移动读取位置):
1 | func (b *Buffer) String() string |
自动增加缓存容量,以保证有 n 字节的剩余空间。
如果 n 小于 0 或无法增加容量则会 panic。
1 | func (b *Buffer) Grow(n int) |
将数据长度截短到 n 字节,如果 n 小于 0 或大于 Cap 则 panic:
1 | func (b *Buffer) Truncate(n int) |
重设缓冲区,清空所有数据(包括初始内容):
1 | func (b *Buffer) Reset() |
eg.
1 | func main() { |
errors
包
Go 语言使用 error 类型来返回函数执行过程中遇到的错误,如果返回的 error 值为 nil,则表示未遇到错误,否则 error 会返回一个字符串,用于说明遇到了什么错误。
其实 error 只是一个接口,定义如下:
1 | type error interface { |
你可以用任何类型去实现它(只要添加一个 Error() 方法即可),也就是说,error 可以是任何类型,这意味着,函数返回的 error 值实际可以包含任意信息,不一定是字符串(当然字符串是必须的)。
error 不一定表示一个错误,它可以表示任何信息,比如 io 包中就用 error 类型的 io.EOF 表示数据读取结束,而不是遇到了什么错误。再比如 path/filepath 包中用 error 类型的 filepath.SkipDir 表示跳过当前目录,继续遍历下一个目录,而不是遇到了什么错误。
error.New()
函数
errors 包实现了一个最简单的 error 类型,只包含一个字符串,它可以记录大多数情况下遇到的错误信息。errors 包的用法也很简单,只有一个 New 函数,用于生成一个最简单的 error 对象:
1 | // 将字符串 text 包装成一个 error 对象返回 |
eg:
1 | func SomeFunc() error { |
自定义error
类型
如果你的程序需要记录更多的错误信息,比如时间、数值等信息,可以声明一个自定义的 error 类型。
1 | package main |
fmt
包
实现了格式化I/O函数。文档
占位符
通用占位符:
1 | %v 值的默认格式。当打印结构体时,“加号”标记(%+v)会添加字段名 |
1 |
|
布尔值:
1 | %t true 或 false |
整数值:
1 | %b 二进制表示 |
浮点及复数:
1 | %b 无小数部分的,指数为二的幂的科学计数法,与 strconv.FormatFloat中的 'b' 转换格式一致。例如 -123456p-78 |
字符串和bytes的slice表示:
1 | %s 字符串或切片的无解译字节 |
指针:
1 | %p 十六进制表示,前缀 0x |
这里没有 ‘u’ 标记。若整数为无符号类型,他们就会被打印成无符号的。类似地,这里也不需要指定操作数的大小(int8,int64)。
对于%v来说默认的格式是:
1 | bool: %t |
对于复合对象,里面的元素使用如下规则进行打印:
1 | struct: {field0 field1 ...} |
宽度和精度:
宽度是在%之后的值,如果没有指定,则使用该值的默认值,精度是跟在宽度之后的值,如果没有指定,也是使用要打印的值的默认精度.例如:%9.2f,宽度9,精度2
1 | %f: default width, default precision |
对数值而言,宽度为该数值占用区域的最小宽度;精度为小数点之后的位数。但对于 %g/%G 而言,精度为所有数字的总数。例如,对于123.45,格式 %6.2f会打印123.45,而 %.4g 会打印123.5。%e 和 %f 的默认精度为6;但对于 %g 而言,它的默认精度为确定该值所必须的最小位数。
对大多数值而言,宽度为输出的最小字符数,如果必要的话会为已格式化的形式填充空格。对字符串而言,精度为输出的最大字符数,如果必要的话会直接截断。
宽度是指”必要的最小宽度”. 若结果字符串的宽度超过指定宽度时, 指定宽度就会失效。
其他标志:
1 | + 总打印数值的正负号;对于%q(%+q)保证只输出ASCII编码的字符。 |
对于每一个 Printf 类的函数,都有一个 Print 函数,该函数不接受任何格式化,它等价于对每一个操作数都应用 %v。另一个变参函数 Println 会在操作数之间插入空白,并在末尾追加一个换行符
格式化错误:
如果给占位符提供了无效的实参(如将一个字符串提供给%d),便会出现格式化错误.所有的错误都始于“%!”,有时紧跟着单个字符(占位符),并以小括号括住的描述结尾。
Scanning
一组类似的函数通过扫描已格式化的文本来产生值。
Scan、Scanf 和 Scanln 从os.Stdin 中读取;
Fscan、Fscanf 和 Fscanln 从指定的 io.Reader 中读取;
Sscan、Sscanf 和 Sscanln 从实参字符串中读取。
Scanln、Fscanln 和 Sscanln在换行符处停止扫描,且需要条目紧随换行符之后;
Scanf、Fscanf 和 Sscanf需要输入换行符来匹配格式中的换行符;
其它函数则将换行符视为空格。
Scanf、Fscanf 和 Sscanf 根据格式字符串解析实参,类似于 Printf。例如,%x会将一个整数扫描为十六进制数,而 %v 则会扫描该值的默认表现格式。
格式化类似于 Printf,但也有例外,如下所示:
1 | %p 没有实现 |
在输入Scanf中,宽度可以理解成输入的文本(%5s表示输入5个字符),而Scanf没有精度这种说法(没有%5.2f,只有 %5f)
函数
Errorf
1 | func Errorf(format string, a ...interface{}) error |
Errorf 根据于格式说明符进行格式化,并将字符串作为满足 error 的值返回,其返回类型是error(功能同Sprintf,只不过把结果字符串包装成error类型).
1 | func main() { |
Fprint、Fprintf、Fprintln
对于每一个 Printf 类的函数,都有一个 Print 函数,该函数不接受任何格式化,它等价于对每一个操作数都应用 %v。另一个变参函数 Println 会在操作数之间插入空白,并在末尾追加一个换行符
1 | func Fprint(w io.Writer, a ...interface{}) (n int, err error) |
Fprint 使用其操作数的默认格式进行格式化并写入到 w。当两个连续的操作数均不为字符串时,它们之间就会添加空格。它返回写入的字节数以及任何遇到的错误。
Fprintf 根据于格式说明符进行格式化并写入到 w。它返回写入的字节数以及任何遇到的写入错误。
Fprintln 使用其操作数的默认格式进行格式化并写入到 w。其操作数之间总是添加空格,且总在最后追加一个换行符。它返回写入的字节数以及任何遇到的错误。
1 | func main() { |
Fscan、Fscanf、Fscanln
1 | func Fscan(r io.Reader, a ...interface{}) (n int, err error) |
Fscan 扫描从 r 中读取的文本,并将连续由空格分隔的值存储为连续的实参。换行符计为空格。它返回成功扫描的条目数。若它少于实参数,err 就会报告原因。
Fscanf 扫描从 r 中读取的文本,并将连续由空格分隔的值存储为连续的实参,其格式由 format 决定。它返回成功解析的条目数。
Fscanln 类似于 Sscan,但它在换行符处停止扫描,且最后的条目之后必须为换行符或 EOF。
注:Fscan类的也是由空格进行分割的.
1 |
|
Print、Printf、Println
1 | func Print(a ...interface{}) (n int, err error) |
Print 使用其操作数的默认格式进行格式化并写入到标准输出。当两个连续的操作数均不为字符串时,它们之间就会添加空格。它返回写入的字节数以及任何遇到的错误。
Printf 根据格式说明符进行格式化并写入到标准输出。它返回写入的字节数以及任何遇到的写入错误。
使用其操作数的默认格式进行格式化并写入到标准输出。其操作数之间总是添加空格,且总在最后追加一个换行符。它返回写入的字节数以及任何遇到的错误。
1 |
|
类似于 Fprint(os.Stdout,...)
Scan、Scanf、Scanln
1 | func Scan(a ...interface{}) (n int, err error) |
Scan 扫描从标准输入中读取的文本,并将连续由空格分隔的值存储为连续的实参。换行符计为空格。它返回成功扫描的条目数。若它少于实参数,err 就会报告原因。
Scanf 扫描从标准输入中读取的文本,并将连续由空格分隔的值存储为连续的实参,其格式由 format 决定。它返回成功扫描的条目数。
Scanln 类似于 Scan,但它在换行符处停止扫描,且最后的条目之后必须为换行符或 EOF。
1 | func main() { |
Sprint、Sprintf、Sprintln
1 | func Sprint(a ...interface{}) string |
Sprint 使用其操作数的默认格式进行格式化并返回其结果字符串。当两个连续的操作数均不为字符串时,它们之间就会添加空格。
Sprintf 根据于格式说明符进行格式化并返回其结果字符串。
Sprintln 使用其操作数的默认格式进行格式化并写返回其结果字符串。其操作数之间总是添加空格,且总在最后追加一个换行符。
1 | func main() { |
Sscan、Sscanf、Sscanln
1 | func Sscan(str string, a ...interface{}) (n int, err error) |
Sscan 扫描实参 string,并将连续由空格分隔的值存储为连续的实参。换行符计为空格。它返回成功扫描的条目数。若它少于实参数,err 就会报告原因。
Scanf 扫描实参 string,并将连续由空格分隔的值存储为连续的实参,其格式由 format 决定。它返回成功解析的条目数。
Sscanln 类似于 Sscan,但它在换行符处停止扫描,且最后的条目之后必须为换行符或 EOF。
1 | func main() { |
type
type Formatter
用于实现对象的自定义格式输出
1 | type Formatter interface { |
type GoStringer
1 | type GoStringer interface { |
type ScanState
ScanState 会返回扫描状态给自定义的 Scanner
Scanner 可能会做字符的实时扫描
或者通过 ScanState 获取以空格分割的 token
1 | type ScanState interface { |
如果在 Scanln、Fscanln 或 Sscanln 中调用该方法
该方法会在遇到 ‘\n’ 或读取超过指定的宽度时返回 EOFReadRune() (r rune, size int, err error)
UnreadRune 撤消最后一次的 ReadRune 操作UnreadRune() error
SkipSpace 跳过输入数据中的空格
在 Scanln、Fscanln、Sscanln 操作中,换行符会被当作 EOF
在其它 Scan 操作中,换行符会被当作空格SkipSpace()
如果参数 skipSpace 为 true,则 Token 会跳过输入数据中的空格
然后返回满足函数 f 的连续字符,如果 f 为 nil,则使用 !unicode.IsSpace 来代替 f
在 Scanln、Fscanln、Sscanln 操作中,换行符会被当作 EOF
在其它 Scan 操作中,换行符会被当作空格
返回的 token 是一个切片,返回的数据可能在下一次调用 Token 的时候被修改Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
Width 返回宽度值以及宽度值是否被设置Width() (wid int, ok bool)
因为 ReadRune 已经通过接口实现,所以 Read 可能永远不会被 Scan 例程调用
一个 ScanState 的实现,可能会选择废弃 Read 方法,而使其始终返回一个错误信息Read(buf []byte) (n int, err error)}
type Scanner
Scanner 由任何拥有 Scan 方法的值实现,它将输入扫描成值的表示,并将其结果存储到接收者中,该接收者必须为可用的指针。Scan 方法会被 Scan、Scanf 或 Scanln 的任何实现了它的实参所调用。
1 | type Scanner interface { |
type State
1 | type State interface { |
type Stringer
1 | type Stringer interface { |
net/http
包
http包包含http客户端和服务端的实现,利用Get,Head,Post,以及PostForm实现HTTP或者HTTPS的请求。
当客户端使用完response body后必须使用close对其进行关闭:
1 | resp, err := http.Get("http://example.com/") |
变量
1 | var ( |
函数
1 | func CanonicalHeaderKey(s string) string//返回header key的规范化形式,规范化形式是以"-"为分隔符,每一部分都是首字母大写,其他字母小写.例如"accept-encoding" 的标准化形式是 "Accept-Encoding". |
eg.
1 | package main |
1 | func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser//该函数类似于io.LimitReader但是该函数是用来限制请求体的大小.与io.LimitReader不同的是,该函数返回一个ReaderCloser,当读超过限制时,返回一个non-EOF,并且当Close方法调用时,关闭底层的reader.该函数组织客户端恶意发送大量请求,浪费服务器资源. |
type Client
1 | type Client//Client是一个http客户端,默认客户端(DefaultClient)将使用默认的发送机制的客户端.Client的Transport字段一般会含有内部状态(缓存TCP连接),因此Client类型值应尽量被重用而不是创建新的。多个协程并发使用Clients是安全的. |
Client的方法:
1 | func (c *Client) Do(req *Request) (resp *Response, err error)//Do发送http请求并且返回一个http响应,遵守client的策略,如重定向,cookies以及auth等.错误经常是由于策略引起的,当err是nil时,resp总会包含一个非nil的resp.body.当调用者读完resp.body之后应该关闭它,如果resp.body没有关闭,则Client底层RoundTripper将无法重用存在的TCP连接去服务接下来的请求,如果resp.body非nil,则必须对其进行关闭.通常来说,经常使用Get,Post,或者PostForm来替代Do. |
http中Client客户端的参数设定解析如上面描述所示,Client具有Do,Get,Head,Post以及PostForm等方法。 其中Do方法可以对Request进行一系列的设定,而其他的对request设定较少。如果Client使用默认的Client,则其中的Get,Head,Post以及PostForm方法相当于默认的http.Get,http.Post,http.Head以及http.PostForm函数。举例说明其用法。其中Get,Head,Post以及PostForm用法如下:
1 | package main |
Do方法可以灵活的对request进行配置,然后进行请求。利用http.Client以及http.NewRequest来模拟请求。模拟request中带有cookie的请求。
1 | package main |
type CloseNotifier 接口
1 | type CloseNotifier//该接口被ResponseWriter用来实时检测底层连接是否已经断开.如果客户端已经断开连接,该机制可以在服务端响应之前取消二者之间的长连接. |
CloseNotifier经常被ResponseWriter用来检测底层连接是否已经断开,举例如下:
1 | func Test(w http.ResponseWriter, r *http.Request) { |
type ConnState int
1 | type ConnState //表示客户端连接服务端的状态 |
其中ConnState常用状态变量如下:
1 | const ( |
1 | func (c ConnState) String() string //状态的字符形式表示 |
type Cookie struct
type Cookie//常用SetCooker用来给http的请求或者http的response设置cookie
1 | type Cookie struct { |
func (c *Cookie) String() string//该函数返回cookie的序列化结果。如果只设置了Name和Value字段,序列化结果可用于HTTP请求的Cookie头或者HTTP回复的Set-Cookie头;如果设置了其他字段,序列化结果只能用于HTTP回复的Set-Cookie头。
type CookieJar//在http请求中,CookieJar管理存储和使用cookies.Cookiejar的实现必须被多协程并发使用时是安全的.
1 | type CookieJar interface { |
type Dir string
type Dir//使用一个局限于指定目录树的本地文件系统实现一个文件系统.一个空目录被当做当前目录”.”
1 | type Dir string |
type File 接口
type File //File是通过FileSystem的Open方法返回的,并且能够被FileServer实现.该方法与*os.File行为表现一样.
1 | type File interface { |
type FileSystem 接口
type FileSystem//实现了对一系列指定文件的访问,其中文件路径之间通过分隔符进行分割.
1 | type FileSystem interface { |
type Flusher 接口
type Flusher //responsewriters允许http控制器将缓存数据刷新入client.然而如果client是通过http代理连接服务器,这个缓存数据也可能是在整个response结束后才能到达客户端.
1 | type Flusher interface { |
type Handler 接口
type Handler //实现Handler接口的对象可以注册到HTTP服务端,为指定的路径或者子树提供服务。ServeHTTP应该将回复的header和数据写入ResponseWriter接口然后返回。返回意味着该请求已经结束,HTTP服务端可以转移向该连接上的下一个请求。
//如果ServeHTTP崩溃panic,那么ServeHTTP的调用者假定这个panic的影响与活动请求是隔离的,二者互不影响.调用者恢复panic,将stack trace记录到错误日志中,然后挂起这个连接.
1 | type Handler interface { |
func FileServer(root FileSystem) Handler // FileServer返回一个使用FileSystem接口提供文件访问服务的HTTP处理器。可以使用httpDir来使用操作系统的FileSystem接口实现。其主要用来实现静态文件的展示。
func NotFoundHandler() Handler //返回一个简单的请求处理器,该处理器对任何请求都会返回”404 page not found”
func RedirectHandler(url string, code int) Handler//使用给定的状态码将它接受到的任何请求都重定向到给定的url
func StripPrefix(prefix string, h Handler) Handler//将请求url.path中移出指定的前缀,然后将省下的请求交给handler h来处理,对于那些不是以指定前缀开始的路径请求,该函数返回一个http 404 not found 的错误.
func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler //具有超时限制的handler,该函数返回的新Handler调用h中的ServerHTTP来处理每次请求,但是如果一次调用超出时间限制,那么就会返回给请求者一个503服务请求不可达的消息,并且在ResponseWriter返回超时错误.
其中FileServer经常和StripPrefix一起连用,用来实现静态文件展示,举例如下:
1 | func main() { |
type HandlerFunc
type HandlerFunc//HandlerFunc type是一个适配器,通过类型转换我们可以将普通的函数作为HTTP处理器使用。如果f是一个具有适当签名的函数,HandlerFunc(f)通过调用f实现了Handler接口。
1 | type HandlerFunc func(ResponseWriter, *Request) |
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) //ServeHttp调用f(w,r)
type Header//代表在http header中的key-value对
1 | type Header map[string][]string |
1 | func (h Header) Add(key, value string)//将key,value组成键值对添加到header中 |
type Hijacker 接口
1 | type Hijacker interface { |
eg.
1 | func HiJack(w http.ResponseWriter, r *http.Request) { |
type ProtocolError
type ProtocolError //http请求解析错误
1 | func (err *ProtocolError) Error() string |
type Reques struct
type Request//代表客户端给服务器端发送的一个请求.该字段在服务器端和客户端使用时区别很大.
1 | type Request struct { |
func NewRequest(method, urlStr string, body io.Reader) (*Request, error) //利用指定的method,url以及可选的body返回一个新的请求.如果body参数实现了io.Closer接口,Request返回值的Body 字段会被设置为body,并会被Client类型的Do、Post和PostForm方法以及Transport.RoundTrip方法关闭。
func ReadRequest(b *bufio.Reader) (req *Request, err error)//从b中读取和解析一个请求.
func (r *Request) AddCookie(c *Cookie) //给request添加cookie,AddCookie向请求中添加一个cookie.按照RFC 6265 section 5.4的规则,AddCookie不会添加超过一个Cookie头字段.这表示所有的cookie都写在同一行,用分号分隔(cookie内部用逗号分隔属性)
func (r Request) Cookie(name string) (Cookie, error)//返回request中指定名name的cookie,如果没有发现,返回ErrNoCookie
func (r Request) Cookies() []Cookie//返回该请求的所有cookies
func (r *Request) SetBasicAuth(username, password string)//利用提供的用户名和密码给http基本权限提供具有一定权限的header。当使用http基本授权时,用户名和密码是不加密的
func (r *Request) UserAgent() string//如果在request中发送,该函数返回客户端的user-Agent
用法eg.
1 | package main |
func (r *Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error)//对于指定格式的key,FormFile返回符合条件的第一个文件,如果有必要的话,该函数会调用ParseMultipartForm和ParseForm。
func (r *Request) FormValue(key string) string//返回key获取的队列中第一个值。在查询过程中post和put中的主题参数优先级高于url中的value。为了访问相同key的多个值,调用ParseForm然后直接检查RequestForm。
func (r Request) MultipartReader() (multipart.Reader, error)//如果这是一个有多部分组成的post请求,该函数将会返回一个MIME 多部分reader,否则的话将会返回一个nil和error。使用本函数代替ParseMultipartForm可以将请求body当做流stream来处理。
func (r *Request) ParseForm() error//解析URL中的查询字符串,并将解析结果更新到r.Form字段。对于POST或PUT请求,ParseForm还会将body当作表单解析,并将结果既更新到r.PostForm也更新到r.Form。解析结果中,POST或PUT请求主体要优先于URL查询字符串(同名变量,主体的值在查询字符串的值前面)。如果请求的主体的大小没有被MaxBytesReader函数设定限制,其大小默认限制为开头10MB。ParseMultipartForm会自动调用ParseForm。重复调用本方法是无意义的。
func (r *Request) ParseMultipartForm(maxMemory int64) error //ParseMultipartForm将请求的主体作为multipart/form-data解析。请求的整个主体都会被解析,得到的文件记录最多 maxMemery字节保存在内存,其余部分保存在硬盘的temp文件里。如果必要,ParseMultipartForm会自行调用 ParseForm。重复调用本方法是无意义的。
func (r *Request) PostFormValue(key string) string//返回post或者put请求body指定元素的第一个值,其中url中的参数被忽略。
func (r *Request) ProtoAtLeast(major, minor int) bool//检测在request中使用的http协议是否至少是major.minor
func (r *Request) Referer() string//如果request中有refer,那么refer返回相应的url。Referer在request中是拼错的,这个错误从http初期就已经存在了。该值也可以从Headermap中利用Header[“Referer”]获取;在使用过程中利用Referer这个方法而不是map的形式的好处是在编译过程中可以检查方法的错误,而无法检查map中key的错误。
func (r *Request) Write(w io.Writer) error//Write方法以有线格式将HTTP/1.1请求写入w(用于将请求写入下层TCPConn等)。本方法会考虑请求的如下字段:Host URL Method (defaults to “GET”) Header ContentLength TransferEncoding Body
如果存在Body,ContentLength字段<= 0且TransferEncoding字段未显式设置为[“identity”],Write方法会显式添加”Transfer-Encoding: chunked”到请求的头域。Body字段会在发送完请求后关闭。
func (r *Request) WriteProxy(w io.Writer) error//该函数与Write方法类似,但是该方法写的request是按照http代理的格式去写。尤其是,按照RFC 2616 Section 5.1.2,WriteProxy会使用绝对URI(包括协议和主机名)来初始化请求的第1行(Request-URI行)。无论何种情况,WriteProxy都会使用r.Host或r.URL.Host设置Host头。
type Response struct
type Response//指对于一个http请求的响应response
1 | type Response struct { |
func Get(url string) (resp *Response, err error)//利用GET方法对一个指定的URL进行请求,如果response是如下重定向中的一个代码,则Get之后将会调用重定向内容,最多10次重定向。
1 | 301 (永久重定向,告诉客户端以后应该从新地址访问) |
//如果有太多次重定向或者有一个http协议错误将会导致错误。当err为nil时,resp总是包含一个非nil的resp.body,Get是对DefaultClient.Get的一个包装。
func Head(url string) (resp *Response, err error)//该函数功能见net中Head方法功能。该方法与默认的defaultClient中Head方法一致。
func Post(url string, bodyType string, body io.Reader) (resp *Response, err error)//该方法与默认的defaultClient中Post方法一致。
func PostForm(url string, data url.Values) (resp *Response, err error)//该方法与默认的defaultClient中PostForm方法一致。
func ReadResponse(r bufio.Reader, req *Request) (Response, error)//ReadResponse从r读取并返回一个HTTP 回复。req参数是可选的,指定该回复对应的请求(即是对该请求的回复)。如果是nil,将假设请 求是GET请求。客户端必须在结束resp.Body的读取后关闭它。读取完毕并关闭后,客户端可以检查resp.Trailer字段获取回复的 trailer的键值对。(本函数主要用在客户端从下层获取回复)
func (r Response) Cookies() []Cookie//解析cookie并返回在header中利用set-Cookie设定的cookie值。
func (r Response) Location() (url.URL, error)//返回response中Location的header值的url。如果该值存在的话,则对于请求问题可以解决相对重定向的问题,如果该值为nil,则返回ErrNOLocation的错误。
func (r *Response) ProtoAtLeast(major, minor int) bool//判定在response中使用的http协议是否至少是major.minor的形式。
func (r *Response) Write(w io.Writer) error//将response中信息按照线性格式写入w中。
type ResponseWriter 接口
type ResponseWriter//该接口被http handler用来构建一个http response
1 | type ResponseWriter interface { |
type RoundTripper 接口
type RoundTripper//该函数是一个执行简单http事务的接口,该接口在被多协程并发使用时必须是安全的。
1 | type RoundTripper interface { |
func NewFileTransport(fs FileSystem) RoundTripper //该函数返回一个RoundTripper接口,服务指定的文件系统。 返回的RoundTripper接口会忽略接收的请求中的URL主机及其他绝大多数属性。该函数的典型应用是给Transport类型的值注册”file”协议。如下所示:
1 | t := &http.Transport{} |
*type ServeMux *
type ServeMux //该函数是一个http请求多路复用器,它将每一个请求的URL和一个注册模式的列表进行匹配,然后调用和URL最匹配的模式的处理器进行后续操作。模式是固定的、由根开始的路径,如”/favicon.ico”,或由根开始的子树,如”/images/“ (注意结尾的斜杠)。较长的模式优先于较短的模式,因此如果模式”/images/“和”/images/thumbnails/“都注册了处理器,后一 个处理器会用于路径以”/images/thumbnails/“开始的请求,前一个处理器会接收到其余的路径在”/images/“子树下的请求。
注意,因为以斜杠结尾的模式代表一个由根开始的子树,模式”/“会匹配所有的未被其他注册的模式匹配的路径,而不仅仅是路径”/“。
模式也能(可选地)以主机名开始,表示只匹配该主机上的路径。指定主机的模式优先于一般的模式,因此一个注册了两个模式”/codesearch”和”codesearch.google.com/“的处理器不会接管目标为”http://www.google.com/"的请求。
ServeMux还会负责对URL路径的过滤,将任何路径中包含”.”或”..”元素的请求重定向到等价的没有这两种元素的URL。(参见path.Clean函数)
func NewServeMux() *ServeMux //初始化一个新的ServeMux
func (mux *ServeMux) Handle(pattern string, handler Handler) //将handler注册为指定的模式,如果该模式已经有了handler,则会出错panic。
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))//将handler注册为指定的模式
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) //根据指定的r.Method,r.Host以及r.RUL.Path返回一个用来处理给定请求的handler。该函数总是返回一个非nil的 handler,如果path不是一个规范格式,则handler会重定向到其规范path。Handler总是返回匹配该请求的的已注册模式;在内建重 定向处理器的情况下,pattern会在重定向后进行匹配。如果没有已注册模式可以应用于该请求,本方法将返回一个内建的”404 page not found”处理器和一个空字符串模式。
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) //该函数用于将最接近请求url模式的handler分配给指定的请求。
举例说明servemux的用法:
1 | package main |
type Server struct
type Server //该结构体定义一些用来运行HTTP Server的参数,如果Server默认为0的话,那么这也是一个有效的配置。
1 | type Server struct { |
func (srv *Server) ListenAndServe() error//监听TCP网络地址srv.Addr然后调用Serve来处理接下来连接的请求。如果srv.Addr是空的话,则使用“:http”。
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error//ListenAndServeTLS监听srv.Addr确定的TCP地址,并且会调用Serve方法处理接收到的连接。必须提供证书文件和对应的私钥文 件。如果证书是由权威机构签发的,certFile参数必须是顺序串联的服务端证书和CA证书。如果srv.Addr为空字符串,会使 用”:https”。
func (srv *Server) Serve(l net.Listener) error//接受Listener l的连接,创建一个新的服务协程。该服务协程读取请求然后调用srv.Handler来应答。实际上就是实现了对某个端口进行监听,然后创建相应的连接。
func (s *Server) SetKeepAlivesEnabled(v bool)//该函数控制是否http的keep-alives能够使用,默认情况下,keep-alives总是可用的。只有资源非常紧张的环境或者服务端在关闭进程中时,才应该关闭该功能。
举例说明Server的用法:
1 | package main |
type Transport struct
type Transport //该结构体实现了RoundTripper接口,支持HTTP,HTTPS以及HTTP代理,TranSport也能缓存连接供将来使用。
1 | type Transport struct { |
func (t *Transport) CancelRequest(req *Request)//通过关闭连接来取消传送中的请求。
func (t *Transport) CloseIdleConnections()//关闭所有之前请求但目前处于空闲状态的连接。该方法并不中断任何正在使用的连接。
func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper)//RegisterProtocol注册一个新的名为scheme的协议。t会将使用scheme协议的请求转交给rt。rt有责任模拟HTTP请求的语义。RegisterProtocol可以被其他包用于提供”ftp”或”file”等协议的实现。
func (t *Transport) RoundTrip(req *Request) (resp *Response, err error)//该函数实现了RoundTripper接口,对于高层http客户端支持,例如处理cookies以及重定向,查看Get,Post以及Client类型。
io/ioutil
包
函数
Discard
Discard 是一个 io.Writer 接口,调用它的 Write 方法将不做任何事情并且始终成功返回。
1 | var Discard io.Writer = devNull(0) |
ReadAll
ReadAll 读取 r 中的所有数据,返回读取的数据和遇到的错误。
如果读取成功,则 err 返回 nil,而不是 EOF,因为 ReadAll 定义为读取所有数据,所以不会把 EOF 当做错误处理。
1 | func ReadAll(r io.Reader) ([]byte, error) |
ReadFile
ReadFile 读取文件中的所有数据,返回读取的数据和遇到的错误。
如果读取成功,则 err 返回 nil,而不是 EOF。
1 | func ReadFile(filename string) ([]byte, error) |
WriteFile
WriteFile 向文件中写入数据,写入前会清空文件。
如果文件不存在,则会以指定的权限创建该文件。
返回遇到的错误。
1 | func WriteFile(filename string, data []byte, perm os.FileMode) error |
ReadDir
ReadDir 读取指定目录中的所有目录和文件(不包括子目录)。
返回读取到的文件信息列表和遇到的错误,列表是经过排序的。
1 | func ReadDir(dirname string) ([]os.FileInfo, error) |
NopCloser
NopCloser 将 r 包装为一个 ReadCloser 类型,但 Close 方法不做任何事情。
1 | func NopCloser(r io.Reader) io.ReadCloser |
TempFile
TempFile 在 dir 目录中创建一个以 prefix 为前缀的临时文件,并将其以读写模式打开。返回创建的文件对象和遇到的错误。
如果 dir 为空,则在默认的临时目录中创建文件(参见 os.TempDir),多次调用会创建不同的临时文件,调用者可以通过 f.Name() 获取文件的完整路径。
调用本函数所创建的临时文件,应该由调用者自己删除。
1 | func TempFile(dir, prefix string) (f *os.File, err error) |
TempDir
TempDir 功能同 TempFile,只不过创建的是目录,返回目录的完整路径。
1 | func TempDir(dir, prefix string) (name string, err error) |
例子
读取目录:
1 | func main() { |
临时目录、临时文件:
1 | func main() { |
os
包
函数
获取当前目录、改变目录
1 | func Getwd() (dir string, err error) //获取当前目录 |
修改文件权限
1 | func Chmod(name string, mode FileMode) error |
获取用户识别码uid 和 群组识别码gid
1 | func Getuid() int |
查看用户所属组的列表
1 | func Getgroups() ([]int, error) |
返回底层系统的内存页面大小
1 | func Getpagesize() int |
获取主机名称
1 | func Hostname() (name string, err error) |
获取当前进程id、父进程id
1 | func Getpid() // 获取当前进程id |
获取文件的状态
1 | func Stat(name string) (FileInfo, error) |
错误检测
1 | func IsExist(err error) bool // 文件存在,但是由系统产生错误 |
创建文件夹、删除文件或文件夹
1 | func Mkdir(name string, perm FileMode) error |
修改文件夹或文件的名称
1 | func Rename(oldpath, newpath string) error |
移动文件夹或文件
1 | func Rename(oldpath, newpath string) error |
新建文件
1 | func Create(name string) (*File, error) |
这个方法创建文件是默认的权限为0666,如果已经存在同名的文件,则调用此方法,会覆盖掉原来的文件
打开文件
1 | func Open(name string) (*File, error) |
如果打开的文件不存在,则会返回错误 open file1.txt: no such file or directory
写入文件
1 | func (f *File) Write(b []byte) (n int, err error) |
要注意的是,os.open() 打开的文件是只读的,写入不成功,需要:
1 | func OpenFile(name string, flag int, perm FileMode) (*File, error) |
例子:
1 | func main() { |
读取文件
1 | func main() { |
关闭文件
1 | func (f *File) Close() error |
检测文件是否是同一个
1 | func SameFile(fi1, fi2 FileInfo) bool |
就算是同一个文件,没在同一个路径下也会返回false,判断依据如下
这意味着两个基础结构的 inode 字段是相同的
获取文件模式相关信息
1 | func (m FileMode) IsDir() bool |
把文件所在的目录切换为当前目录
1 | func (f *File) Chdir() error |
查看文件名称
1 | func (f *File) Name() string |
如何查看所有文件夹下的所有文件和文件数量
1 | func (f *File) Readdir(n int) ([]FileInfo, error) |
读取文件夹的下面文件的名称
1 | func (f *File) Readdirnames(n int) (names []string, err error) |
获取临时陌路的文件夹路径
1 | func TempDir() string |
判断字符是否是支持的路径分隔符
1 | func IsPathSeparator(c uint8) bool |
查看环境变量
1 | func Getenv(key string) string |
查找指定环境变量
1 | func func Expand(s string, mapping func(string) string) string |
获取文件对应的unix文件描述符
1 | func (f *File) Fd() uintptr |
Chown修改文件的用户ID和组ID
1 | func Chown(name string, uid, gid int) error |
修改文件权限
1 | func (f *File) Chmod(mode FileMode) error |
强制改变文件大小
两个方法:
1 | func Truncate(name string, size int64) error |
减小文件大小会造成内容丢失。
链接 硬链接
硬链接(hard link, 也称链接)就是一个文件的一个或多个文件名。再说白点,所谓链接无非是把文件名和计算机文件系统使用的节点号链接起来。因此我们可以用多个文件名与同一个文件进行链接,这些文件名可以在同一目录或不同目录
1 | func Link(oldname, newname string) error |
同步保存当前文件的内容
1 | func (f *File) Sync() error |
Sync递交文件的当前内容进行稳定的存储。一般来说,这表示将文件系统的最近写入的数据在内存中的拷贝刷新到硬盘中稳定保存
1 | func main() { |
NewFile使用给出的Unix文件描述符和名称创建一个文件
1 | func NewFile(fd uintptr, name string) *File |
Lstat返回一个描述name指定的文件对象的FileInfo
1 | func Lstat(name string) (fi FileInfo, err error) |
Lstat返回一个描述name指定的文件对象的FileInfo。如果指定的文件对象是一个符号链接,返回的FileInfo描述该符号链接的信息,本函数不会试图跳转该链接。如果出错,返回的错误值为*PathError类型
查看所有环境变量、清除环境变量
1 | func Environ() []string |
获取当前程序可执行的文件地址
1 | func Executable() (string, error) |
让程序已给定的状态码退出
Exit让当前程序以给出的状态码code退出。一般来说,状态码0表示成功,非0表示出错。程序会立刻终止,defer的函数不会被执行
1 | func Exit(code int) |
设置环和取消环境变量
1 | func Unsetenv(key string) error |
创建软链接
1 | func Symlink(oldname, newname string) error |
获取软链接文件对应的实际文件路径地址
1 | func Readlink(name string) (string, error) |
更改指定文件的访问和修改时间
1 | func Chtimes(name string, atime time.Time, mtime time.Time) error |
第二个参数访问时间 第三个参数修改时间
1 | os.Chtimes("/Users/xujie/Desktop/file.txt",time.Now(),time.Now().Add(time.Hour * 24)) |
创建文件夹,并设置权限
1 | func MkdirAll(path string, perm FileMode) error |
规则:
- 如果已经存在同名文件夹,则此方法不做任何事情
- 文件夹里面所有文件都是同样的权限
设置文章的读写位置
1 | func (f *File) Seek(offset int64, whence int) (ret int64, err error) |
Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误
1 | eg: |
file.Seek(offset,0) offset = 0
从文件中读取10个数据,之后偏移量设置为offset = 10,则从文件内容第11个字节开始读取,当Read方法读取文件到结尾时,会返回EOF标识,这个时候程序退出for循环
修改文件权限
1 | func Lchown(name string, uid, gid int) error |
管道的用法
1 | func Pipe() (r *File, w *File, err error) |
这个方法主要在协程之间进行数据传递,r.read 方法会等待接受w文件中写数据
1 | func main() { |
创建系统错误
1 | func NewSyscallError(syscall string, err error) error |
通过pid查找进行进程
1 | func FindProcess(pid int) (*Process, error) |
查找增加运行的进程,但是在 Unix 系统上,无论过程是否存在,FindProcess 都会成功并为给定的 PID 返回一个 Process
杀死进程
1 | func (p *Process) Kill() error |
1 | func main() { |
释放与进程p关联的任何资源
1 | func (p *Process) Release() error |
Release释放进程p绑定的所有资源, 使它们(资源)不能再被(进程p)使用。只有没有调用Wait方法时才需要调用本方法
1 | func (p *Process) Signal(sig Signal) error |
runtime
包
runtime 包 提供了运行时与系统的交互,比如控制协程函数,触发垃圾立即回收等等底层操作
函数
获取GO的信息
1 | func GOROOT() string // 获取GOROOT环境变量 |
设置cpu profile记录的速率
1 | func SetCPUProfileRate(hz int) |
SetCPUProfileRate设置CPU profile记录的速率为平均每秒hz次。如果hz<=0,SetCPUProfileRate会关闭profile的记录。如果记录器在执行,该速率必须在关闭之后才能修改。
绝大多数使用者应使用runtime/pprof包或testing包的-test.cpuprofile选项而非直接使用SetCPUProfileRate
立即执行一次垃圾回收
1 | func GC() |
给变量绑定方法,当垃圾回收的时候进行监听
1 | func SetFinalizer(x, f interface{}) |
注意x必须是指针类型,f 函数的参数一定要和x保持一致,或者写interface{},不然程序会报错
1 | type Student struct { |
查看内存申请和分配统计信息
1 | func ReadMemStats(m *MemStats) |
查看程序
1 | func (r *MemProfileRecord) InUseBytes() int64 // InUseBytes返回正在使用的字节数(AllocBytes – FreeBytes) |
MemProfile返回当前内存profile中的记录数n。若len(p)>=n,MemProfile会将此分析报告复制到p中并返回(n, true);如果len(p)< n,MemProfile则不会更改p,而只返回(n, false)。
如果inuseZero为真,该profile就会包含无效分配记录(其中r.AllocBytes>0,而r.AllocBytes==r.FreeBytes。这些内存都是被申请后又释放回运行时环境的)。
大多数调用者应当使用runtime/pprof包或testing包的-test.memprofile标记,而非直接调用MemProfile
执行一个断点
1 | func Breakpoint() |
获取程序调用go协程的栈踪迹历史
1 | func Stack(buf []byte, all bool) int |
Stack将调用其的go程的调用栈踪迹格式化后写入到buf中并返回写入的字节数。若all为true,函数会在写入当前go程的踪迹信息后,将其它所有go程的调用栈踪迹都格式化写入到buf中。
获取当前函数或者上层函数的标识号、文件名、调用方法在当前文件中的行号
1 | func Caller(skip int) (pc uintptr, file string, line int, ok bool) |
获取与当前堆栈记录相关链的调用栈踪迹
1 | func Callers(skip int, pc []uintptr) int |
函数把当前go程调用栈上的调用栈标识符填入切片pc中,返回写入到pc中的项数。实参skip为开始在pc中记录之前所要跳过的栈帧数,0表示Callers自身的调用栈,1表示Callers所在的调用栈。返回写入p的项数。
获取一个标识调用栈标识符pc对应的调用栈
1 | func FuncForPC(pc uintptr) *Func |
1 | func (f *Func) Name() string // 获取调用栈所调用的函数的名字 |
获取当前进程执行的cgo调用次数
1 | func NumCgoCall() int64 |
获取当前存在的go协程数
1 | func NumGoroutine() int |
终止掉当前的go协程
1 | func Goexit() |
Goexit终止调用它的go协程,其他协程不受影响,Goexit会在终止该go协程前执行所有的defer函数,前提是defer必须在它前面定义,如果在main go协程调用本方法,会终止该go协程,但不会让main返回,因为main函数没有返回,程序会继续执行其他go协程,当其他go协程执行完毕后,程序就会崩溃.
让其他go协程优先执行,等其他协程执行完后,在执行当前的协程
1 | func Gosched() |
获取活跃的go协程的堆栈profile以及记录个数
1 | func GoroutineProfile(p []StackRecord) (n int, ok bool) |
将调用的go协程绑定到当前所在的操作系统线程,其它go协程不能进入该线程
1 | func LockOSThread() |
将调用的go程绑定到它当前所在的操作系统线程。除非调用的go程退出或调用UnlockOSThread,否则它将总是在该线程中执行,而其它go程则不能进入该线程
1 | func UnlockOSThread() |
将调用的go程解除和它绑定的操作系统线程。若调用的go程未调用LockOSThread,UnlockOSThread不做操作
获取线程创建profile中的记录个数
1 | func ThreadCreateProfile(p []StackRecord) (n int, ok bool) |
返回线程创建profile中的记录个数。如果len(p)>=n,本函数就会将profile中的记录复制到p中并返回(n, true)。若len(p)< n,则不会更改p,而只返回(n, false)。
绝大多数使用者应当使用runtime/pprof包,而非直接调用ThreadCreateProfile。
控制阻塞profile记录go协程阻塞事件的采样率
1 | func SetBlockProfileRate(rate int) |
SetBlockProfileRate控制阻塞profile记录go程阻塞事件的采样频率。对于一个阻塞事件,平均每阻塞rate纳秒,阻塞profile记录器就采集一份样本。
要在profile中包括每一个阻塞事件,需传入rate=1;要完全关闭阻塞profile的记录,需传入rate<=0。
返回当前阻塞profile中的记录个数
1 | func BlockProfile(p []BlockProfileRecord) (n int, ok bool) |
BlockProfile返回当前阻塞profile中的记录个数。如果len(p)>=n,本函数就会将此profile中的记录复制到p中并返回(n, true)。如果len(p)< ,本函数则不会修改p,而只返回(n, false)。
绝大多数使用者应当使用runtime/pprof包或testing包的-test.blockprofile标记, 而非直接调用 BlockProfile。
sort
包
sort包中实现了3种基本的排序算法:插入排序.快排和堆排序.和其他语言中一样,这三种方式都是不公开的,他们只在sort包内部使用.所以用户在使用sort包进行排序时无需考虑使用那种排序方式,sort.Interface定义的三个方法:获取数据集合长度的Len()方法、比较两个元素大小的Less()方法和交换两个元素位置的Swap()方法,就可以顺利对数据集合进行排序。sort包会根据实际数据自动选择高效的排序算法。
type Interface
1 | type Interface interface { |
任何实现了 sort.Interface 的类型(一般为集合),均可使用该包中的方法进行排序。这些方法要求集合内列出元素的索引为整数。
golang自身实现的interface有三种,Float64Slice,IntSlice,StringSlice
1 |
|
Search 二分法查找
func Search(n int, f func(int) bool) int
使用二分法查找(常用于一个已排序、可索引的数据结构,如数组、切片),查找范围是[0:n],返回能使f(i)=true的最小i(0 <= i < n),并且会假定,如果f(i)=true,则f(i+1)=true,即对于切片[0:n],i之前的切片元素会使f()函数返回false,i及i之后的元素会使f()函数返回true。但是,当在切片中无法找到时f(i)=true的i时(此时切片元素都不能使f()函数返回true),Search()方法会返回n(而不是返回-1)。
为了查找某个值,而不是某一范围的值时,如果slice以升序排序,则 f func中应该使用>=,如果slice以降序排序,则应该使用<=。
1 | package main |
1 | func SearchFloat64s(a []float64, x float64) int |
其中需要注意的是,以上三种search查找方法,其对应的slice必须按照升序进行排序,否则会出现奇怪的结果.
Stable 排序
func Stable(data Interface)
:Stable对data进行排序,不过排序过程中,如果data中存在相等的元素,则他们原来的顺序不会改变,即如果有两个相等元素num,他们的初始index分别为i和j,并且i < j,则利用Stable对data进行排序后,i依然小于j.直接利用sort进行排序则不能够保证这一点.
Reverse 逆序排序
1 | func Reverse(data Interface) Interface |
strconv
包
与字符串相关的类型转换。
包含了一些变量用于获取程序运行的操作系统平台下 int 类型所占的位数,如:strconv.IntSize
。
任何类型 T 转换为字符串总是成功的。
数字 → 字符串:
strconv.Itoa(i int) string
返回数字 i 所表示的字符串类型的十进制数。strconv.FormatFloat(f float64, fmt byte, prec int, bitSize int) string
将64位浮点型数字转换为字符串,其中fmt
表示格式(其值可以是b
、e
、f
或g
),prec
表示精度,bitSize
则使用 32 表示 float32,用 64 表示 float64。
将字符串转换为其他类型 tp 并不总是可能的,可能会在运行时抛出错误 parsing "…": invalid argument
。
字符串 → 数字类型:
strconv.Atoi(s string) (i int, err error)
将字符串转换为 int 型。strconv.ParseFloat(s string, bitSize int) (f float64, err error)
将字符串转换为 float64 型。
利用多个返回值的特性(第 1 个是转换后的结果(若成功),第 2 个是可能出现的错误),一般使用如下形式进行从字符串到其它类型的转换:
1 | val, err = strconv.Atoi(s) |
strings
包
Go 中使用 strings
包对字符串进行操作。中文文档、 官方文档 或 国内访问文档
前、后缀
HasPrefix
判断字符串 s
是否以 prefix
开头:
1 | strings.HasPrefix(s, prefix string) bool |
HasSuffix
判断字符串 s
是否以 suffix
结尾:
1 | strings.HasSuffix(s, suffix string) bool |
字符串包含关系
Contains
判断字符串 s
是否包含 substr
:
1 | strings.Contains(s, substr string) bool |
func ContainsAny(s, chars string) bool
: 判断字符串s是否包含chars中任意一个字符,若chars为空,返回false
func ContainsRune(s string, r rune) bool
: 是否包含r rune
索引字符串位置
Index
返回字符串 str
在字符串 s
中的第一次出现的索引(str
的第一个字符的索引),
返回 -1
表示 s
不包含 str
:
1 | strings.Index(s, str string) int |
LastIndex
返回 str
在 s
中最后出现的所有(第一个字符),
返回 -1
表示 s
不包含 str
:
1 | strings.LastIndex(s, str string) int |
建议用 IndexRune
查询非 ASCII 编码的字符在字符串中的位置(返回 -1
表示 s
不包含 str
: ):
1 | strings.IndexRune(s string, r rune) int |
字符串替换
Replace
用于将字符串 str
中的前 n
个字符串 old
替换为字符串 new
,并范围一个新的字符串,如果 n = -1
啧替换所有有 old
为 new
:
1 | strings.Replace(str, old, new, n) string |
返回的是str的副本
统计字符串出现的次数
Count
用于统计字符串 str
中字符串 s
出现的非重叠次数:
1 | strings.Count(s, str string) int |
重复字符串
Repeat
用于重复 count
次字符串 s
并返回一个新的字符串:
1 | strings.Repeat(s, count int) string |
修改字符串大小写
ToLower
将字符串中的 Unicode 字符全部转换为相应的小写字符:
1 | strings.Tolower(s) string |
ToUpper
将字符串中的 Unicode 字符全部转换为相应的大写字符:
1 | strings.ToUpper(s) string |
ToTitle
s 中的所有字符修改为其 Title 格式:
1 | func ToTitle(s string) string |
修剪字符串
strings.TrimSpace(s)
用于剔除字符串开头和结尾的空白符号;strings.Trim(s, "cut")
用于剔除字符串开头和结尾的 cut
;TrimLeft
或者 TrimRight
用于只剔除开头或结尾的字符串。
1 | func TrimSpace(s string) string |
注:TrimSuffix只是去掉s字符串结尾的suffix字符串,只是去掉1次,而TrimRight是一直去掉s字符串右边的字符串,只要有响应的字符串就去掉,是一个多次的过程,这也是二者的本质区别.
分割字符串
strings.Fields(s)
会利用 1 个或多个空白符号(\t, \n, \v, \f, \r, ‘ ‘, U+0085 (NEL), U+00A0 (NBSP))来作为动态长度的分隔符将字符串分割成若干小块,并返回一个 slice,如果字符串只包含空白符号,则返回一个长度为 0 的空 slice。
strings.Split(s, sep)
用于自定义分割符号来对指定字符串进行分割,同样范围 slice。
因为这 2 个函数都会返回 slice,所以习惯使用 for - range 循环来对其进行处理。
拼接 slice 到字符串
Join
用于将元素类型为 string 的 slice 使用分割符号来拼接组成一个字符串:
1 | strings.Join(sl [string], sep string) string |
从字符串中读取内容
strings.NewReader(str)
用于生成一个 ‘Reader’ 并读取字符串中的内容,然后返回指向该 Reader
的指针,从其他类型读取内容的函数还有:Read
从 []byte 中读取内容;ReadByte()
和 ReadRune()
从字符串中读取下一个 byte 或者 rune。
比较两字符串字典顺序
func Compare(a, b string) int
return 0 if a==b, -1 if a < b, and +1 if a > b.
但不常用,通常用 go 自身的 ==, >, < 来比较,更快更易懂。
忽略大小写判断s和t是否相等
func EqualFold(s, t string) bool
Map
func Map(mapping func(rune) rune, s string) string
:s 中满足 mapping(rune) 的字符替换为 mapping(rune) 的返回值。如果 mapping(rune) 返回负数,则相应的字符将被删除。
1 | func Slash(r rune) rune { |
reader.go
Reader结构
1 | // Reader 结构通过读取字符串,实现了 io.Reader,io.ReaderAt, |
Len 返回 r.i 之后的所有数据的字节长度
1 | func (r *Reader) Len() int |
Read 将 r.i 之后的所有数据写入到 b 中(如果 b 的容量足够大)
返回读取的字节数和读取过程中遇到的错误
如果无可读数据,则返回 io.EOF
1 | func (r *Reader) Read(b []byte) (n int, err error) |
ReadAt 将 off 之后的所有数据写入到 b 中(如果 b 的容量足够大)
返回读取的字节数和读取过程中遇到的错误
如果无可读数据,则返回 io.EOF
如果数据被一次性读取完毕,则返回 io.EOF
1 | func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) |
ReadByte 将 r.i 之后的一个字节写入到返回值 b 中
返回读取的字节和读取过程中遇到的错误
如果无可读数据,则返回 io.EOF
1 | func (r *Reader) ReadByte() (b byte, err error) |
UnreadByte 撤消前一次的 ReadByte 操作,即 r.i–
1 | func (r *Reader) UnreadByte() error |
ReadRune 将 r.i 之后的一个字符写入到返回值 ch 中
ch: 读取的字符
size:ch 的编码长度
err: 读取过程中遇到的错误
如果无可读数据,则返回 io.EOF
如果 r.i 之后不是一个合法的 UTF-8 字符编码,则返回 utf8.RuneError 字符
1 | func (r *Reader) ReadRune() (ch rune, size int, err error) |
撤消前一次的 ReadRune 操作
1 | func (r *Reader) UnreadRune() error |
Seek 用来移动 r 中的索引位置
offset:要移动的偏移量,负数表示反向移动
whence:从那里开始移动,0:起始位置,1:当前位置,2:结尾位置
如果 whence 不是 0、1、2,则返回错误信息
如果目标索引位置超出字符串范围,则返回错误信息
目标索引位置不能超出 1 << 31,否则返回错误信息
1 | func (r *Reader) Seek(offset int64, whence int) (int64, error) |
WriteTo 将 r.i 之后的数据写入接口 w 中
1 | func (r *Reader) WriteTo(w io.Writer) (n int64, err error) |
replace.go
Replacer 根据一个替换列表执行替换操作
1 | type Replacer struct { |
NewReplacer 通过“替换列表”创建一个 Replacer 对象
按照“替换列表”中的顺序进行替换,只替换非重叠部分。
如果参数的个数不是偶数,则抛出异常。
如果在“替换列表”中有相同的“查找项”,则后面重复的“查找项”会被忽略
1 | func NewReplacer(oldnew ...string) *Replacer |
Replace 返回对 s 进行“查找和替换”后的结果
Replace 使用的是 Boyer-Moore 算法,速度很快
1 | func (r *Replacer) Replace(s string) string |
WriteString 对 s 进行“查找和替换”,然后将结果写入 w 中
1 | func (r *Replacer) WriteString(w io.Writer, s string) (n int, err error) |
sync
包
临时对象池
Pool 用于存储临时对象,它将使用完毕的对象存入对象池中,在需要的时候取出来重复使用,目的是为了避免重复创建相同的对象造成 GC 负担过重。其中存放的临时对象随时可能被 GC 回收掉(如果该对象不再被其它变量引用)。
从 Pool 中取出对象时,如果 Pool 中没有对象,将返回 nil,但是如果给 Pool.New 字段指定了一个函数的话,Pool 将使用该函数创建一个新对象返回。
Pool 可以安全的在多个例程中并行使用,但 Pool 并不适用于所有空闲对象,Pool 应该用来管理并发的例程共享的临时对象,而不应该管理短寿命对象中的临时对象,因为这种情况下内存不能很好的分配,这些短寿命对象应该自己实现空闲列表。
Pool 在开始使用之后,不能再被复制。
1 | type Pool struct { |
Once
Once 的作用是多次调用但只执行一次,Once 只有一个方法,Once.Do(),向 Do 传入一个函数,这个函数在第一次执行 Once.Do() 的时候会被调用,以后再执行 Once.Do() 将没有任何动作,即使传入了其它的函数,也不会被执行,如果要执行其它函数,需要重新创建一个 Once 对象。
Once 可以安全的在多个例程中并行使用。
多次调用仅执行一次指定的函数 f:
1 | func (o *Once) Do(f func()) |
eg:
1 | func main() { |
互斥锁
互斥锁用来保证在任一时刻,只能有一个例程访问某对象。Mutex 的初始值为解锁状态。Mutex 通常作为其它结构体的匿名字段使用,使该结构体具有 Lock 和 Unlock 方法。
Mutex 可以安全的在多个例程中并行使用。
1 | // Locker 接口包装了基本的 Lock 和 UnLock 方法,用于加锁和解锁。 |
eg:
1 | type SafeInt struct { |
读写互斥锁
RWMutex 比 Mutex 多了一个“读锁定”和“读解锁”,可以让多个例程同时读取某对象。RWMutex 的初始值为解锁状态。RWMutex 通常作为其它结构体的匿名字段使用。
Mutex 可以安全的在多个例程中并行使用。
1 | // Lock 将 rw 设置为写锁定状态,禁止其他例程读取或写入。 |
组等待
WaitGroup 用于等待一组例程的结束。主例程在创建每个子例程的时候先调用 Add 增加等待计数,每个子例程在结束时调用 Done 减少例程计数。之后,主例程通过 Wait 方法开始等待,直到计数器归零才继续执行。
1 | // 计数器增加 delta,delta 可以是负数。 |
eg:
1 | func main() { |
条件等待
条件等待通过 Wait 让例程等待,通过 Signal 让一个等待的例程继续,通过 Broadcast 让所有等待的例程继续。
在 Wait 之前应当手动为 c.L 上锁,Wait 结束后手动解锁。为避免虚假唤醒,需要将 Wait 放到一个条件判断循环中。官方要求的写法如下:
1 | c.L.Lock() |
Cond 在开始使用之后,不能再被复制。
1 | type Cond struct { |
eg:
1 | func main() { |
time
包:时间和日期
包中包括了两类时间:时间点(某一时刻)和时长(某一个时间段)time
包提供了一个数据类型 time.Time
(作为值使用)以及显示和测量时间和日期的功能函数。
获取当前时间:time.Now()
;
1 | var t time.Time = time.Now() |
获取时间的一部分: t.Day
、t.Minute()
…
自定义时间格式化字符串:eg.fmt.Printf("%02d.%02d.%4d\n", t.Day(), t.Month(), t.Year())
将会输出 08.03.2019
Duration 类型表示两个连续时刻所相差的纳秒数,类型为 int64。Location 类型映射某个时区的时间,UTC 表示通用协调世界时间。
包中的一个预定义函数 func (t Time) Format(layout string) string
可以根据一个格式化字符串来将一个t转换为相应格式的字符串,你可以使用一些预定义的格式,如:time.ANSIC
或 time.RFC822
。
1 | fmt.Println((t.Format("02 Jan 2006 15:04"))) |
如果需要在应用程序在经过一定时间或周期执行某项任务(事件处理的特例),则可以使用 time.After
或者 time.Ticker
。
另外,time.Sleep(Duration d)
可以实现对某个进程(实质上是 goroutine)时长为 d 的暂停。
时间敞亮(时间格式化)
1 | const ( |
这些常量是在time包中进行time 格式化 和time解析而预定义的一些常量,其实他们使用的都是一个特定的时间:Mon Jan 2 15:04:05 MST 2006
函数
time 组成
time.Duration
时间长度,消耗时间time.Time
时间点time.C
放时间的通道(tine.C := make(chan time.Time))
After 函数
1 | func After(d Duration) <-chan Time |
表示多少时间之后,但是在去除channel内容之前不阻塞,后续程序可以继续执行。
1 | func Sleep(d Duration) |
表示休眠多少时间,休眠时处于阻塞状态,后续程序无法执行。
鉴于After特性,其通常用来处理程序超时问题,如下所示:
1 | select { |
1 | func Tick(d Duration) <-chan Time |
time.Tick(time.Duration)用法和time.After差不多,但是它是表示每隔多少时间之后,是一个重复的过程,其他与After一致。
1 | type Duration int64 |
1 | type Location |
1 | type Month // 定义了1年的12个月 |
1 | type ParseError |
1 | type Ticker |
例子:
使用时间控制停止ticker:
1 | ticker := time.NewTicker(time.Millisecond * 500) |
使用channel控制停止ticker:
1 | ticker := time.NewTicker(time.Millisecond * 500) |
这种情况下,在执行num次以Ticker时间为单位的函数之后,c channel中已满,以后便不会再执行对应的函数
1 | type Time //包括日期和时间 |
1 | func Now() Time //返回当前时间,包括日期,时间和时区 |
例子:
1 | t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC) |
1 | func (t Time) Second() int //获取时间t的秒 |
例子:
1 | t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645") |
1 | func (t Time) UTC() Time //将本地时间变换为UTC时区的时间并返回 |
1 | type Timer //用于在指定的Duration类型时间后调用函数或计算表达式,它是一个计时器 |
1 | type Weekday |
一些例子:
获取年月日方法
1 | t := time.Now() |
获取格式为:2017-12-29 16:58:39
1 | t := time.Now() |
获取三个小时之前的时间
1 | du, _ := time.ParseDuration("-3h") |
获取三天之前的时间
1 | t := time.Now() |
t.AddDate(year,month,day) 正数向前,负数向后
时间戳转time.Time 类型
1 | timestamp := 1513580645 |
获取时间戳:
1 | t := time.Now() |
两个时间的间隔
1 | t1 := time.Now() |
字符串转时间
1 | layout := "2006-01-02 15:04:05" |
标准时间字符串转化为时间
使用byte读取数据库当中的timestamp字段时,会出现标准的时间格式
1 | layout := "2006-01-02T15:04:05Z07:00" |
unicode
包
常量
1 | const ( |
RangeTable
1 | // 判断字符 r 是否在 rangtab 范围内。 |
判断及转换字符大小写、Title
1 | // 判断字符 r 是否为大写格式 |
示例1:判断汉字:
1 | func main() { |
示例2:判断大小写:
1 | func main() { |
示例3:输出 Unicode 规定的标题字符
1 | func main() { |
示例4:转换大小写
1 | func main() { |
rune操作
1 | // ToUpper 将 r 转换为大写格式 |
eg.
1 | func main() { |
SimpleFold 环绕查找
1 | // SimpleFold 在 Unicode 字符表中从字符 r 开始环绕查找(到尾部后再从头开始) |
eg.
1 | func main() { |
判断
1 | // IsDigit 判断 r 是否为一个十进制的数字字符 |
eg.
1 | func main() { |
eg.判断汉字和标点:
1 | func main() { |
eg.输出所有 mark 字符:
1 | func main() { |
unicode/utf16
包
1 | // IsSurrogate 判断 r 是否为代理区字符 |
eg.
1 | func main() { |
unicode/utf8
包
常量
1 | // 编码所需的基本数字 |
函数
1 | // 将 r 转换为 UTF-8 编码写入 p 中(p 必须足够长,通常为 4 个字节) |
eg.
1 | func main() { |
to be continued...