Go知识梳理
学习方法
1. 了解全局:进行一个全局的了解,知道要学习什么 1. 搜索,对学习的东西有一个基本的认识 2. 确定范围:集中精力,确定要学什么 1. 考虑到时间 3. 定义目标:明确成功的含义 1. 具体的,无二义性的 4. 寻找资源 5. 创建学习计划 6. 筛选资源 7. 开始学习,浅尝辄止 8. 动手操作,边学边玩 9. 全面掌握,学以致用 1. 真实有用的项目 2. 能够一直迭代维护的项目 10. 乐为人师,融会贯通
Golang概述
1. 诞生 2. 创造原因 3. 发展历程 4. 特点: 1. 继承了c语言的很多理念,保留了和c一样的编译方法,但是同时弱化了指针 2. 引入了包的概念,go的文件都要依赖于一个包 3. 垃圾回收机制,不需要开发人员管理 4. 天然并发(重要特点) 1. 从语言方面实现,简单 2. Gorutine,轻量级线程,可以实现大并发处理,高效利用多核 3. 基于cps并发模型实现 5. 管道机制 6. 函数可以返回多个值 7. 新的创新:切片,延时执行defer 5. 开发工具: 6. 格式:gofmt可以格式化
变量和常量
1、变量的声明方法
var a int //声明后不赋值 var a = 10 //类型推导 a := 10 //类型推导
2、批量声明
var ( a int b string d bool )
3、匿名 : _ 如果某个值不想接收,使用下划线
4、变量类型
5、> 恒定不变的值,使用 const 定义
const pi = 3.14 const pi float32= 3.1
6、定义多个常量
const( n1 = 100 n2 n3 ) //如果省略了,表示值和上面一行相同
7、iota
const ( n = iota //0 n1 //1 n2 //2 ) //注意:多个iota定义在1行,值相同
8、字符串不可以修改,需要先转成[]rune 或 []byte ,然后再转换成string
9、类型转换:go只有强转
a := string(b)
10、统计汉字的个数
func main() { cs:=0 s := "hello 你哈" for _, c := range s { if unicode.Is(unicode.Han,c){ cs++ } } fmt.Println(cs) }
11、位运算符
运算符 | 描述 |
& | 参与运算的两数各对应的二进位相与。 (两位均为1才为1) |
| | 参与运算的两数各对应的二进位相或。 (两位有一个为1就为1) |
^ | 参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1) |
<< | 左移n位就是乘以2的n次方。 “a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。 |
>> | 右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。 |
流程控制
1. if else 2. for 3. for range 4. switch case 1. fallthrough, 执行完这个case之后 ,会执行下个case 5. goto 6. break 7. continue
type switch
数组
1、定义一个长度为n的数组
- 长度必须是常量,并且长度是数组类型的一部分,一旦定义,长度不能改变
- 数组的长度是数据类型的一部分 [2]int 和 [3]int 不是一种数据类型
var a [3]int
2、数组的初始化
1. 使用初始化列表来设置数组元素的值 var a = [3]int{1,2} 2. 不设置值的时候,数组会自动初始化为int类型的零值 var a [3]int 3. 根据初始值的个数判断数组长度 var a = [...]int{1,2,34} 4. 类型推导的方式
3、数组的遍历
for for range
4、二维数组
(1)多维数组只有第一层可以使用[…]让编译器推导数组长度
5、组是值类型,传参不会改变原本的值
6、注意:
- 数组支持 == ,!= 操作符,因为内存总是被初始化过的
- [n]*T 表示指针数组, *[n]T 表示数组指针
切片
1.引子:数组的长度固定并且数组长度属于类型的一部分,所以数组又很多的局限性,例如
func sum (x [3]int) int{ sum := 0 for _,v := range x{ sum += v } return sum } //这个函数只能接受[]int类型,其他的都不支持
再比如:
a := [3]int{1,2,3} //定义了三个元素了,就不能再就行往数组a中添加新元素了
2.切片的定义
var a []T
3.声明和初始化
var a []T
4.长度和容量
(1)切片拥有自己的长度和容量,我们可以通过内置的len()函数求长度,使用cap()求容量
5.切片的底层是一个数组,可以通过数组直接得到切片
a:= [5]int{1,2,3,4,5} s:= a[1:3] //做保
6.使用make()函数构造切片
make([]T, size, cap)
7.切片的本质
切片本质是对底层数组的封装,包含了三个信息,底层数组的指针、切片的长度和切片的容量
8.判断切片是否为空,时钟使用len(s),判定而不是s == nil 判定
9.切片之间不能比较,我们不能使用 == 操作符来判断切片是否包含的元素是否相等
10.切片可以和nil比较, 一个nil值的切片并没有底层数组,一个nil值的切片长度和容量都是0,但是一个切片长度和容量都是0的切片是nil
11.append方法
12.切片指向一个底层数组,如果这个数组的容量够用就添加新元素。如果不够用就会自动扩容。
13.扩容策略
newcap := old.cap doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { if old.len < 1024 { newcap = doublecap } else { // Check 0 < newcap to detect overflow // and prevent an infinite loop. for 0 < newcap && newcap < cap { newcap += newcap / 4 } // Set newcap to the requested cap when // the newcap calculation overflowed. if newcap <= 0 { newcap = cap } } }
14.copy函数
可以赋值一个切片给一个独立的数据空间切片,即改变原切片和数组不会影响被复制的切片
var a = [...]int{1, 2, 3, 4, 5} fmt.Printf("%T\n", a) b := a[0:3] fmt.Printf("%T\n", b) var c = make([]int, 10) copy(c, b) fmt.Println("==========") fmt.Println(a) fmt.Println(b) fmt.Println(c)
15.string切片
string是不可变的,所以也可以切片,但是切片的值不可以改变