指针
Go语言保留了指针,但与C语言指针有所不同。主要体现在:
- 默认值 nil
- 操作符 “&” 取变量地址, “*” 通过指针访问目标对象
- 不支持指针运算,不支持 “->” 运算符,直接⽤ “.” 访问目标成员
函数new
表达式new(T)将创建一个T类型的匿名变量,所做的是为T类型的新值分配并清零一块内存空间,然后将这块内存空间的地址作为结果返回,而这个结果就是指向这个新的T类型值的指针值,返回的指针类型为*T。
new创建的内存空间位于heap上,空间的默认值为数据类型默认值。如:new(int) 则 *p为0,new(bool) 则 *p为false
func main() {
var p1 *int
p1 = new(int) //p1为*int 类型, 指向匿名的int变量
fmt.Println("*p1 = ", *p1) //*p1 = 0
p2 := new(bool) //p2为*bool 类型, 指向匿名的bool变量
fmt.Println("*p2 = ", *p2) //*p2 = false
*p2 = true
fmt.Println("*p2 = ", *p2) //*p1 = true
}
指针做函数参数
func swap01(a, b int) {
a, b = b, a
fmt.Printf("swap01 a = %d, b = %d\n", a, b)
}
func swap02(x, y *int) {
*x, *y = *y, *x
}
func main() {
a := 10
b := 20
//swap01(a, b) //值传递(传值)
swap02(&a, &b) //地址传递(传引用)
fmt.Printf("a = %d, b = %d\n", a, b)
}
关于多重赋值
https://www.jianshu.com/p/de95ef71162d
切片(slice)
为什么要有切片?
- 数组的容量固定,不能自动拓展。
- 值传递。 数组作为函数参数时,将整个数组值拷贝一份给形参(值拷贝内存消耗大)。
在Go语言中,我们几乎可以在所有的场景中,使用切片替换数组使用。
- 一个slice由三个部分构成:指针、长度和容量。
切片并不是数组或数组指针,它通过内部指针和相关属性引⽤数组⽚段,以实现变⻓⽅案。(后续通过阅读源码深入了解)
切片创建
可以用make关键字:
s := make([]int, 5)
注意:make只能创建slice、map和channel,并且返回一个有初始值(非零)的对象。
切片截取
截取可表示为s[low:high:max]。
- low:表示下标的起点。
- high:表示下标的终点(左闭右开,不包括此下标)。
- 长度 len = high – low。
- 容量 cap = max – low。
长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。
切片作为函数参数时,传引用
append函数
append函数会智能的将底层数组的容量增长,一旦超过原底层数组容量,通常以2倍(1024以下)容量重新分配底层数组,并复制原来的数据。
因此,使用append 给切片做扩充时,切片的地址可能发生变化。但,数据都被重新保存了,不影响使用
copy函数
函数 copy 在两个 slice 间复制数据,复制⻓度以 len 小的为准,两个 slice 指向同⼀底层数组。直接对应位置覆盖。
- copy(目标位置切片, 源切片)
map
Go语言中的map(映射、字典)是一种内置的数据结构,它是一个无序的key-value对的集合,比如以身份证号作为唯一键来标识一个人的信息。
Go语言中并没有提供一个set类型,但是map中的key也是不相同的,可以用map实现类似set的功能。
map的格式:
map[keyType]valueType
在一个map里所有的键都是唯一的,而且必须是支持==和!=操作符的类型,切片、函数以及包含切片的结构类型这些类型由于具有引用语义,不能作为映射的键,使用这些类型会造成编译错误。
注意:map是无序的,我们无法决定它的返回顺序,所以,每次打印结果的顺利有可能不同。
创建map
m := make(map[int]string, 10) //第2个参数指定容量
赋值
-
如果新map元素的key与原map元素key相同 ——> 覆盖(替换)
-
如果新map元素的key与原map元素key不同 ——> 添加
遍历
Map的迭代顺序是不确定的,并且不同的哈希函数实现可能导致不同的遍历顺序。在实践中,遍历的顺序是随机的,每一次遍历的顺序都不相同。
判断map中key是否存在:
value, ok := m[1]
-
如果key存在,第一个返回值返回value的值。第二个返回值为 true。
-
如果key存在,第一个返回值返回value的值。第二个返回值为 true。
删除
使用delete()函数,指定key值可以方便的删除map中的k-v映射。
delete(m1, 2) //删除key值为2的map
map 做函数参数和返回值,传引用。
结构体
比较
如果结构体的全部成员都是可以比较的,那么结构体也是可以比较的,那样的话两个结构体将可以使用 == 或 != 运算符进行比较,但不支持 > 或 <
做函数参数
传参过程中,实参会将自己的值拷贝一份给形参。因此结构体“传值”操作几乎不会在实际开发中被使用到。近乎100%的使用都采用“传址”的方式,将结构体的引用传递给所需函数。
字符串处理函数
具体可参考Golang标准库文档
除Contains、Join、Trim、Replace等我们学过的字符串处理函数之外,以下函数也常常会被用到。
字符串分割
- func Split(s, sep string) []string
功能:把s字符串按照sep分割,返回slice
按空格拆分字符串
- func Split(s, sep string) []string
功能:把s字符串按照sep分割,返回slice
判断字符串后缀
- func HasSuffix(s, suffix string) bool
功能:判断s字符串是否有后缀子串suffix
判断字符串前缀
- func HasPrefix(s, prefix string) bool
功能:判断s字符串是否有前缀子串suffix
文件IO
打开、创建文件:
- 创建文件 Create: 文件不存在创建,文件存在,将文件内容清空。
- 参数:name, 打开文件的路径: 绝对路径、相对路径 目录分割符:/
- 打开文件 Open: 以只读方式打开文件。文件不存在,打开失败。
- 参数:name, 打开文件的路径: 绝对路径、相对路径
- 打开文件 OpenFile: 以只读、只写、读写 方式打开文件。文件不存在,打开失败。
-
参1:name, 打开文件的路径: 绝对路径、相对路径
-
参2:打开文件权限: O_RDONLY、O_WRONLY、O_RDWR
-
参3:一般传 6
写文件:
按字符串写:
WriteString() --> n个写入的字符个数
n, err := f.WriteString("123")
回车换行: windows: \r\n Linux: \n
按位置写:
Seek(): 修改文件的读写指针位置。
-
参1: 偏移量。 正:向文件尾偏, 负:向文件头偏
-
参2: 偏移起始位置:
io.SeekStart: 文件起始位置
io.SeekCurrent: 文件当前位置
io.SeekEnd: 文件结尾位置
返回值:表示从文件起始位置,到当前文件读写指针位置的偏移量。
off, _ := f.Seek(-5, io.SeekEnd)
按字节写:
writeAt(): 在文件制定偏移位置,写入 []byte , 通常搭配 Seek()
-
参1: 待写入的数据
-
参2:偏移量
返回:实际写出的字节数。
n, _ = f.WriteAt([]byte(“1111”), off)
读文件:
按行读
- 创建一个带有缓冲区的 Reader(读写器)
reader : = bufio.NewReader(打开的文件指针)
- 从reader的缓冲区中 ,读取指定长度的数据。数据长度取决于 参数 dlime
buf, err := reader.ReadBytes('\n') 按行读。
判断到达文件结尾:
if err != nil && err == io.EOF
到文件结尾。
文件结束标记,是要单独读一次获取到的。
缓冲区:内存中的一块区域,用来减少物理磁盘访问操作。《计算硬件及组成原理》 —— 机械工业出版社。
按字节读、写文件。
-
read([]byte): 按字节读文件
-
write([]byte):按字节字节
目录操作:
打开目录: OpenFile
打开目录 OpenFile: 以只读方式打开目录。
-
参1:name, 打开目录的路径: 绝对路径、相对路径
-
参2:打开目录权限: O_RDONLY
-
参3:os.ModeDir
返回值: 返回一个可以读目录的 文件指针。
读目录:Readdir
函数原型:
func (f *File) Readdir(n int) ([]FileInfo, error) {
//参数: 欲打开的目录项个数。 -1 , 表所有
//返回值:FileInfo :
}
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}