GoLang学习总结

一、变量定义

 学习链接

var a int
var b bool
var c int8

var (
	m int
	n string
)

var name string = "china"

func main() {
	age := 18 //生命变量age同时初始化;编译器会根据右边的初始值推断出age是什么类型
}

二、常量定义

const PI = 3.1415926
const KB = 1024

iota
	Go中借助iota来实现枚举
	① iota在const关键字出现时将被重置为0
	② const中每新增一行常量生命将使iota累加一次
	③ const生命的常量后面没有内容默认就跟上一行一致

三、基本数据类型

String
	使用双引号表示字符串 "hello"
	使用单引号表示字符 'h'
整形
	int int8 int16 int32 int64
	uint uint8 uint16 uint32 uint64

浮点型
	float32 float64
	浮点数永远都是不准确
	处理浮点数的方法:
		① 转换成字符串去做运算
		② 整体放大多少倍转换成整数进行运算
复数
	complex64 complex128

布尔
	var a bool //默认是false
	var b = true

	Go语言中布尔值不能和其他类型做转换

byte和rune
	英文字符用byte(ASCII码能表示)
	rune(中文,UTF-8编码)
	字符串中存在中文的时候用rune

四、流程控制

if
for
switch和case

以下了解为主
goto+label

continue+label

break+label

五、格式化打印参数

学习链接

六、数组

学习链接

七、切片

切片与数组的区别是没有固定的长度,切片本质就是一个数组,是语言层面对数组的封装;
切片三要素:
	① 地址 (切片中第一个元素指向的内存空间)
	② 大小 (切片中目前元素的个数) len()
	③ 容量 (底层数组最大能存放的元素的个数) cap()

得到切片的三种方式:
	① 直接声明 a := []int{1, 2, 3} len:3 cap:3
	② 基于数组得到切片 m := [5]int 	b:= m[:3] len:3 cap:5
	③ 基于切片再得到切片  b := a[:2] len:2 cap:3

切片支持自动扩容,扩容策略分为三种:
	① 每次只追加一个元素,每一次的容量是上一次的2倍;
	② 追加的超过原来容量的1倍,就等于原来的容量+扩容元素个数的最接近的偶数;
	③ 如果切片的容量大于了1024,后续就每次扩容0.25倍;

make初始化切片:
make:用来给引用类型(常用引用类型:切片和map)做初始化(申请内存空间);
	切片必须初始化,或者用append才能使用;
	var s []int
	s = make([]int, 大小, 容量)

八、指针

指针和地址的区别:
	地址:就是内存地址(用字节来描述的内存地址)
	指针:指针是带类型的。
$和*
	$ : 表示取地址
	* : 根据地址取值

 九、结构体

1. 结构体的所有字段在内存中是连续的
2. 结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字、个数和类型)
3. 结构体进行type重新定义(相当于取别名),Golang认为是新的数据类型,但是相互间可以强转
4. struct的每个字段上,可以写上一个tag,该tag可能通过反射机制获取,常见的使用场景就是序列化和反序列化.
5. 如果1个struct内部字段存储的数据量很大,重复copy造成内存开销过大,自定义1个构造函数返回指针类型的struct

十、接口

1. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例),即可以把struct变量付给interface变量
2. 接口中所有的方法都没有方法体,即都是没有实现的方法。
3. 在 Golang 中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口。
4. 一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型
5. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。
6. Golang 接口中不能有任何变量
7. interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil
8. 空接口 interface{} 没有任何方法,所以所有类型都实现了空接口, 即我们可以把任何一个变量赋给空接口.

十一、goroutine

1. 并发和并行
2. goroutine是用户态线程(程序员通过写代码控制);
3. 启动goroutine:
    ① 使用go关键字
    ② 一个goroutine对应一个函数,这个函数就是要做的事情;
4. goroutine的原理
    ① M:N 将m个goroutine调度到n个操作系统线程上。n默认是操作系统的逻辑核心数;
5. goroutine和OS线程的区别:
    ① goroutine是用户态的线程,初始开销大小很小(2KB),可以随着需求扩充,最大能达1G;
    ② 一个OS线程是很重量级的,通常内存开销达2MB;
    ③ 通过runtime.GOMAXPROCS() 用来设置Go并发使用的CPU核数,1.5版本之后默认跑满CPU;
6. goroutine的特点:
    ① 一个goroutine对应一个函数,这个函数就是要做的事情;
    ② main函数就是一个goroutine;
    ③ 当goroutine对应的函数返回的时候goroutine就结束了;
    ④ main函数所在的goroutine结束了,由它启动的那些goroutine也就结束了
7. sync.WaitGroup
    ① 它是一个结构体类型 var wg sync.WaitGroup
    ② 三个方法:
        wg.Add(n)
        wg.Done()
        wg.Wait()

 十二、channel

1. channel是一种类型,一种引用的类型;
2. channel的声明和初始化:
    var ch chan int
    channel声明之后要用make函数初始化之后才能使用,ch = make(chan int, [cap])
3. channel的三个操作:
    发送:ch <- 100
    接收;<- ch 可以使用变量接收值: a := <- ch 也可以直接丢弃:<- ch
    关闭:chose(ch) 
        关闭后的通道还是可以取值,取完之后返回的类型零值;
        关闭的通道不能再发送值;
        关闭的通道不能再关闭;
4. 无缓冲区和有缓冲区
    无缓冲区channel又称为同步channel,必须有接收才能发送;
    有缓冲区的channel,超过容量就阻塞;
5. 优雅地从通道取值(能判断通道是否被关闭)
    v, ok := <- ch  如果通道被关闭ok返回的事false
    for v := range {}
6. 单向通道
    只能接收(<-ch)或者只能发送(ch<-)的通道;
    多用在函数传参的时候,限制某个通道在函数中只能做什么类型的操作;
7. select多路复用
    同一时刻可以对多个通道做操作;

十三、并发控制与锁

1. 很多并发的场景下需要gouroutine之间做协同处理;
2. 如果多个goroutine操作同一个全局变量的时候,就会出现数据竞争问题;
3. 互斥锁
    ① sync.Mutex 它是一个结构体类型
    ② 声明锁
        var lock sync.Mutex
    ③ 操作
        加锁:lock.Lock()
        解锁: lock.Unlock()
4. 读写锁
    ① sync.RWLock() 适用于读多写少的场景,类比网站数据库的读完分离;
    ② 声明读写锁
        var rwLock sync.RWMutex()
    ③ 操作
        加读锁: rwLock.RLock()
        解读锁: rwLock.Runlock()
        加写锁: rwLock.Lock()
        解写锁: rwLock.Unlock()
5. sync.Map 
    ① 内置的map不是并发安全的;
    ② 并发场景下推荐使用sync.Map
6. sync.Once
    ① 闭包使用

其他

1、 那些数据类型使用for range 
    ① 字符串
    ② 数组(包括切片)
    ③ map

2、变量定义过程
    ① 变量命名
    ② 变量初始化,用于申请内存
3、make和new
    make:用来给引用类型(常用引用类型:切片slice、map、chan)做初始化(申请内存空间);
        切片必须初始化,或者用append才能使用;
        var s []int
        s = make([]int, 大小, 容量)
    new: 用来创建值类型;比如int struct。返回的是指针
        var a = new(int)
4、GoLang与PHP接口的区别:
    ① PHP中通过实例类或抽象类来显式实现implements接口interface(接口中定义了要实现的方法);
    ② Golang中通过隐式实现接口,即只要一个类型实现了接口中规定的所有方法(实际是结构体接收者方法),那么它就实现了这个接口;
5、结构体初始化方法
    type Rect struct {
        x, y float64
        width, height float64
    }
    ① rect1 := new(Rect)
    ② rect2 := &Rect{}
    ③ rect3 := &Rect{0, 0, 100, 200}
    ④ rect4 := &Rect{width:100, height:200}

你可能感兴趣的:(Go,golang)