一、输入/输出
Go语言将IO操作封装在以下几个包中。
io:为I/O原语(I/O primitives)提供基本的接口,在io包中最重要的是两个接口——Reader和Writer接口。
io/ioutil:封装一些实用的I/O函数,这个包主要提供了一些常用、方便的I/O操作函数。
fmt:实现格式化I/O,类似C语言中的printf和scanf。
bufio:实现带缓冲的I/O。它封装于io.Reader和io.Writer对象,创建了另一个对象(Reader和Writer),在提供缓冲的同时实现了一些文本I/O的功能。
1、io:基本I/O接口
1)Reader接口
定义如下:
type Reader interface{
Read(p []byte) (n int, err error)
}
ReadFrom函数将io.Reader作为参数,也就是说,ReadFrom可以从任意地方读取数据,只要来源实现了io.Reader接口。
2)Writer接口
定义如下:
type Writer interface{
Writer(p []byte) (n int, err error)
}
实现一个io.Writer接口,必须遵循以下规则:
(1)Write方法向底层数据流写入len(p)字节的数据,这些数据来自于切片p;
(2)返回被写入的字节数n,其中0<=n<=len(p);
(3)如果n<len(p),则必须返回一些非nil的err(和Read一样);
(4)如果中途出现问题,也要返回非nil的err;
(5)Write方法绝对不能修改切片p以及其中的数据。
2、fmt:格式化I/O
1)Print序列函数
Fprint/Fprintf/Fprintln函数的第一个参数接收一个io.Writer类型,会将内容输出到io.Writer中去。
Print/Printf/Println函数是将内容输出到标准输出中,因此,直接调用F类函数做这件事,并将os.Stdout作为第一个参数传入。
Sprint/Sprintf/Sprintln只是格式化内容为string类型,而并不输出到某处,需要格式化字符串并返回时,可以用Stdout函数。
Sprintf/Fprintf/Printf函数通过指定的格式输出或格式化内容;Sprintf/Fprint/Print函数只是使用默认的格式输出或格式化内容;Sprintln/Fprintln/Println函数使用默认的格式输出或格式化内容,同时会在最后加上“换行符”。
2)Stringer接口
定义如下:
type Stringer interface{
String() string
}
根据Go语言中实现接口的定义,一个类型只有String() string方法,就说它实现了Stringer接口。
3)Formatter接口
定义如下:
type Formatter interface{
Format(f State, c rune)
}
4)GoStringer函数
定义如下:
type GoStringer interface{
GoString() string
}
5)Scan序列函数
Fscan/Fscanf/Fscanln函数的第一个参数接收一个io.Reader类型,从其中读取内容并赋值给相应的实参。
Scan/Scanf/Scanln正是从标准输出获取内容,因此,直接调用F类函数做这件事,并将os.Stdin作为第一个参数传入。
Sscan/Sscanf/Sscanln则直接从字符串中获取内容。
3、文本处理
二、文件系统
1、os:系统功能实现
2、path:兼容路径操作
path/filepath包涉及路径操作时,路径分隔符使用os.PathSeparator。
1)解析路径名字符串
Dir()和Base()函数将一个路径名字符串分解成目录和文件名两部分。
func Dir(path string) string
func Base(path string) string
Dir()返回路径中除去最后一个路径元素的部分,即该路径最后一个元素所有的目录。
Base()函数返回路径的最后一个元素。
Ext()可以获得路径中文件名的扩展名。
func Ext(path string) string
Ext函数返回path文件扩展名。扩展名是路径中最后一个从“.”开始的部分,包括“.”。如果该元素没有“.”会返回空字符串。
2)相对路径和绝对路径
IsAbs()函数可以判断返回的路径是否一个绝对路径:
func IsAbs(path string) bool
Abs()函数返回path代表的绝对路径。
func Abs(path string) (string, error)
Rel()函数返回一个相对路径。
func Rel(basepath, targpath string) (string, error)
3)路径的切分和拼接
对于一个常规文件路径,可以通过Split函数得到它的目录路径和文件名:
func Split(path string) (dir, file string)
4)规整化路径
Clean()函数通过单纯的词法操作返回和path代表同一地址的最短路径:
func Clean(path string) string
5)文件路径匹配
Match()指定name是否和shell的文件模式匹配。模式语法如下:
func Match(pattern, name string) (matched bool, err error)
Glos函数:
func Glob(pattern string) (matches []stirng, err error)
6)遍历目录
在filepath中,提供了Walk()函数,用于遍历目录树。
func Walk(root string, walkFn WalkFunc) error
walkFn的类型WalkFunc的定义如下:
type WalkFunc func(path string, info os.FileInfo, err error) error
三、数据结构与算法
数学方面的包主要是math——实现数学函数计算,math的子包包含以下这些包:
math/big:大整数的高精度计算实现。
math/cmplx:复数基本函数操作。
math/rand:伪随机数生成器。
Go语言在数据结构方面主要有三大相关的标准包:
sort:包含基本的排序方法,支持切片数据排序以及用户自定义数据集合排序。
index/suffixary:该包实现了后缀数组相关算法以支持许多常见的字符串操作。
container:该包实现了三个复杂的数据结构,即堆、链表和环。这个包表示使用这三个数据结构的时候不需要再费心从头开始写算法。
1、排序
Go语言中实现了四种基本排序算法:插入排序、归并排序、堆排序和快速排序。
实现sort.Interface定义的三个方法:获取数据集合长度的Len()方法、比较两个元素大小和Less()方法和交换两个元素位置的Swap()方法,就可以顺利对数据集合进行排序。
1)数据集合排序
代码如下:
package main
import (
"fmt"
"sort"
)
type StuScore struct {
name string
score int
}
type StuScores []StuScore
func (s StuScores) Len() int {
return len(s)
}
func (s StuScores) Less(i, j int) bool {
return s[i].score < s[j].score
}
func (s StuScores) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func main() {
stus := StuScores{
{"张三", 95},
{"李四", 91},
{"赵五", 96},
{"王六", 90}}
fmt.Println("======默认======")
for _, v := range stus {
fmt.Println(v.name, ":", v.score)
}
fmt.Println()
sort.Sort(stus)
fmt.Println("=====排序之后=====")
for _, v := range stus {
fmt.Println(v.name, ":", v.score)
}
fmt.Println("是否已经排序?", sort.IsSorted(stus))
}
运行结果如下:
======默认======
张三 : 95
李四 : 91
赵五 : 96
王六 : 90
=====排序之后=====
王六 : 90
李四 : 91
张三 : 95
赵五 : 96
是否已经排序? true
2)切片排序
[]int排序、[]float64排序、[]string排序
2、container
1)堆
type Interface interface{
sort.Interface
Push(x interface{}) //添加一个元素x并返回Len()
Pop() interface{} //移除并返回元素长度Len()-1
}
2)链表
type Element struct{
next, prev *Element //上一个元素和下一个元素
list *List //元素所有链表
Value interface{} //元素
}
type List struct{
root Element //链表的根元素
len int //链表的长度
}
代码如下:
package main
import (
"container/list"
"fmt"
)
func main() {
list := list.New()
list.PushBack(1)
list.PushBack(2)
fmt.Printf("长度:%v\n", list.Len())
fmt.Printf("第一元素:%#v\n", list.Front())
fmt.Printf("第二元素:%#v\n", list.Front().Next())
}
运行结果如下:
长度:2
第一元素:&list.Element{next:(*list.Element)(0xc0000621e0), prev:(*list.Element)(0xc000062180), list:(*list.List)(0xc000062180), Value:1}
第二元素:&list.Element{next:(*list.Element)(0xc000062180), prev:(*list.Element)(0xc0000621b0), list:(*list.List)(0xc000062180), Value:2}
3)环
type Ring struct{
next, prev *Ring
value interface{}
}
代码如下:
package main
import (
"container/ring"
"fmt"
)
func main() {
ring := ring.New(3)
for i := 1; i <= 3; i++ {
ring.Value = i
ring = ring.Next()
}
s := 0
ring.Do(func(p interface{}) {
s += p.(int)
})
fmt.Println("和为:", s)
}
运行结果如下;
和为: 6