1. 1.1 make vs newhistorical

    1. 是什么 golang的内置函数 2. 为什么需要 分配内存空间 值类型的声明之后即可使用 引用类型的则需要分配空间 3. 使用 3.1. new 开辟一段内存,并置为零值,返回指向该类型内存地址的指针 3.1.1. 相当于&结构体{} 3.2. make 用于创建slice、map和chann

  2. 1.2 reflectionhistorical

    1. 反射是什么 修改代码- 编译- 运行 正常来说我们要修改代码只能在编译前,反射能让我们在运行时修改代码 2. Golang如何实现反射 interface 当向interface变量赋予一个实体类型的时候,interface会存储实体的类型信息,反射就是通过interface的类型信息实现的

  3. 1.3 errorhistorical

    1. exception和error Golang把错误分成exception和error - exception是严程序内部的BUG或者不可预料的情况 - error则是可以预期的,通过一个返回值来判断 2. 使用 2.1. exception - 内部BUG通过recovery捕获转换成erro

  4. 1.4 interfacehistorical

    1. 有哪些 1.1. 空接口interface{} 可以接收任意类型的数据 它只要记录这个数据在哪儿,是什么类型的就足够了 1.1.1. 举例 底层结构如下 - 赋值 - 1.2. 非空接口 非空接口就是有方法列表的接口类型 一个变量要想赋值给一个非空接口类型,其类型必须要实现该接口要求的所有方法

  5. 1.5 functionhistorical

    1. 是什么 - 函数是一等公民 - 有具名函数、匿名函数 - 把函数绑定在struct上就成了方法 2. 使用 2.1. 可变参数 2.2. 多返回值 go语言的函数可以返回多个值 2.2.1. 原理 - C语言的实现 在调用函数中分配返回值的空间,并将返回值的指针传给被调函数 - Go语言的实现

  6. 1.6 stringhistorical

    1. 字符集 计算机只能存储字节(二进制),因此字符肯定也是用字节存储的 但是存储后怎么显示呢?需要建立字节和字符的映射,这就是字符集 比如 - 1.1. Unicode字符集 - 由来 最开始只有ASCII字符集,只支持英文; 为了支持中文简体,推出GB2312; 为了支持中文繁体,推出BIG5.

  7. 1.7 maphistorical

    1. 什么是map O(1)效率存取k-v对 2. map如何实现 数组。数组中每个元素叫做桶 2.1. 写入 2.2. 读取 3. 如何找到key所属的桶 - 第一种:取模运算:hash%m - 第二种:按位与运算:hash&(m-1) - 这里m必须是2的幂次 4. 冲突了怎么办 - 开放寻址法

  8. 1.8 unsafehistorical

    1. 指针类型 1.1. 是什么 变量的地址 1.2. 为什么需要指针类型 使用指针类型可以让callee修改caller传递的值 1.3. Golang的指针类型 Golang的指针类型是安全的 - 不能进行数学运算 - 不同类型的指针不能相互转换 - 不同类型的指针不能使用 == 或 != 比较

  9. 1.9 panic和recoverhistorical

    1. 是什么 - panic是内置函数,可以停止正常的流程。 - recover是内置函数,可以捕获到panic,recover只在defer函数中有用。 2. 为什么需要 - panic一般用于不可恢复的错误,让程序不能继续进行 - recover为了防止panic之后整个进程都down掉,这个时

  10. 1.10 类型系统historical

    1. 有哪些类型 1.1. 内置类型 1.2. 自定义类型 2. 类型元数据是什么 不管是内置类型哈还是自定义类型都有类型元数据,这些类型元数据共同构成了Go语言的类型系统 不管是内置类型还是自定义类型,都有一个对象头 2.1. 内置类型 内置类型除了对象头之外,还会有额外信息 2.1.1. 举例

  11. 1.11 arrayhistorical

    1. 是什么 定长的数组 2. 使用 2.1. 数组的长度也是类型 2.2. 数组是值传递 赋值和函数传参时候是复制一份新的数组 2.3. 可以用range迭代 3. 原理 3.1. 数据结构 3.2. 创建 3.2.1. 初始化 - 第一种方式 会调用到cmd/compile/internal/t

  12. 1.12 slicehistorical

    1. slice 是什么 支持动态扩容的数组 2. 为什么需要 slice array 元素长度固定,无法动态扩容 3. 如何使用 slice 3.1. 基本使用 3.2. 函数传参是引用 - 虽然传的是引用,但是为了避免扩容后 slice 改变,函数返回 slice 3.3. nil slice

  13. 1.13 deferhistorical

    1. 什么是defer 让函数可以在当前函数执行完毕后执行的一种机制。 这里的函数执行完毕包括通过return正常结束或者panic导致的异常结束 2. 为什么需要defer 减少资源泄露的发生 3. 如何使用 在创建资源语句的附件,使用defer释放资源 3.1. 关闭资源 3.2. defer和

  14. 2.1 contexthistorical

    1. context goroutine的上下文,在 goroutine 之间传递上下文信息,包括:取消信号、超时时间、截止时间、k-v 等。 控制并发的其中一种方式,另外一种是sync.WaitGroup.md 2. 使用 2.1. deadlines:超时取消 2.2. cancellation

  15. 2.2 sync.WaitGrouphistorical

    1. 是什么 一种控制并发的方式 让一个goroutine等待其他goroutine完成 类似于9.CountDownLatch.md 2. 使用 3. 原理 - 里面维护了一个counter计数器 - Add 增加计数器 - Done 计数器-1 - Wait 等待计数器到达0时往下执行 4. 参

  16. 2.3 synchistorical

    1. 是什么 提供了基本的 synchronization primitives 除了 Once 和 WaitGroup 外,大部分都是给 low-level 的库使用的 high-level 一般使用 channels 2. 有什么 2.1. Locker - 是个接口 - 有Lock和Unloc

  17. 2.4 sync.maphistorical

    1. sync.map是什么 - 线程安全的Map - 底层使用乐观锁实现,所以适用竞争不大的场景 - 一次写多次读,如缓存的场景 - 多个goroutine读写的是没有交集的key 1.1. 并发安全的思路 - 加一把大锁 - 把map分成若干map,只操作小map 2. 使用 3. 源码分析 3

  18. 2.5 sync.poolhistorical

    1. 是什么 保存temp object的pool。 temp表示这个对象可能会被回收,所以这个pool其实就是个cache 2. 为什么需要 将暂时不用的对象缓存起来,待下次需要的时候直接使用 这样就不用经过内存分配,减轻GC的压力 3. 怎么使用 3.1. fmt - Printf - Fpri

  19. 2.6 selecthistorical

    1. 是什么 - 类似于IO多路复用 - 监听多个阻塞的事件,如果事件发生了,那么执行该事件逻辑 - 如果没有发生并有默认的事件,那么执行默认的事件逻辑 - 如果没有发生且没有默认的事件,那么一直阻塞 2. 使用 2.1. 基本使用 代码执行到 select 时,case 语句会按照源代码的顺序被评

  20. 2.7 sync.Oncehistorical

    1. 是什么 Once 是一个对象,它提供了保证某个动作只被执行一次功能 说白了就是使方法只执行一次 2. 使用 2.1. 单例模式 单例模式.md 3. 原理 通过sync.atomic+sync.Mutex实现 - Do 方法为什么不直接 o.done == 0 而要使用 atomic.Load

  21. 2.8 sync.Mutexhistorical

    1. Mutex是什么 - 互斥锁 - 实现了Locker接口,zero-value是没加锁的状态 - 加锁解锁可以在不同的goroutine中 2. 使用 2.1. 不使用Mutex的情况 2.2. 使用Mutex的情况

  22. 2.9 sync.RWMutexhistorical

    1. 是什么 - 实现了Locker接口,是个读写锁 - Lock , RLock 分别用于加写锁和读锁 - Unlock , RUnlock 分别用于解写锁和读锁 2. 使用

  23. 2.10 sync.Condhistorical

    1. 是什么 - 条件变量。Locker和Cond的关系类似于Java中Lock和Condition的关系。 - 所有方法必须持有Lock才能调用 - func NewCond(l Locker) Cond 使用Lock创建一个Cond - func (c Cond) Wait() 自动释放Lock

  24. 2.11 atomichistorical

    1. atomic是什么 原子性 - 一个或多个操作要么全部执行,要么全部不执行。 - 最小的不可并行化的操作,就是同一时刻最多只有一个并发体对资源进行操作 - 一般情况下,原子操作都是通过“互斥”访问来保证的,通常由特殊的CPU指令提供保护 2. atomic value是什么 atomic包把底

  25. 2.12 channelhistorical

    1. CSP并发模型 - 从内存的角度看,并行计算只有两种: 共享内存 、 消息通信 - 基于共享内存的并发模型通常提供互斥锁作为同步原语 - CSP 全称是 “Communicating Sequential Processes”,是一种基于消息通信的并发模型,由Tony Hoare于1977年提

  26. 2.13 concurrenthistorical

    1. 有什么 1.1. goroutine+channel - goroutine.md - channel.md 1.2. sync包 sync.md 2. 同步 2.1. 顺序一致性模型 同一个Goroutine线程内部,顺序一致性内存模型是得到保证的 2.2. happens-before 不

  27. 2.14 goroutinehistorical

    1. goroutine是什么 - 程序、进程、线程.md - Go语言实现的用户线程 - 相比较于线程,goroutine - 创建、销毁和切换:都在用户态完成无需进入内核 - 内存占用:默认栈大小为2K,并且可以动态扩缩容 2. goroutine使用 2.1. 创建协程 - go f(x, y

  28. 2.15 协程池historical

    1. 协程池是什么 复用goroutine的池子 2. 为什么需要协程池 跟如何设计池化技术.md不同,由于 goroutine创建、销毁对象开销小:创建销毁是在用户态, goroutine数量理论上可以无限,一个goroutine占用内存仅仅不到2K 所以99%的情况下不需要协程池 但是在极限情况

  29. 3.1 GMPhistorical

    1. goroutine调度器 - Golang中协程的调度模型,即有M个线程,N个协程,该怎么分配协程给线程执行 - 这个本质上和操作系统的调度器类似,即有M个处理器,N个线程,怎么分配处理器给线程执行 1.1. GM模型 - 最开始采用的是GM模型 - G:goroutine,M:内核线程 -

  30. 3.2 逃逸分析historical

    1. 逃逸分析 如果是Java或C++创建出来的对象一般都是分配在堆上的,而Golang new出来的对象会根据逃逸分析决定是分配在堆还是栈上 2. 为什么需要逃逸分析 堆 栈 --- ----------- ------------- 回收 需要垃圾回收 退出函数即销毁 空间 大 小 3. 如何逃

  31. 3.3 Go构建过程historical

    1. 文本文件 保存之后这个文件以二进制形式存储在磁盘中 使用vim打开,敲入 :%!xxd 最左边的地址列,中间是文本字符对应的十六进制ASCII编码,最右边是文本字符。 ASCII表可以通过 man ascii 查询 像这种把二进制通过字符表转换成人类可读的文件叫做文本文件,不可读的就是二进制文

  32. 3.4 内存管理historical

    1. Golang内存分区 1.1. 栈 Golang栈管理.md 1.2. 堆 Golang堆管理.md 1.3. 全局区-静态全局变量区 - 全局变量+常量 - 分配:进程启动时 - 回收:进程退出时,由操作系统回收 1.4. 代码区 2. Golang runtime.MemStat Top

  33. 3.5 plan9汇编historical

    1. Plan9汇编是什么 - 伪汇编 - 跟汇编一样需要通过汇编器转换成机器指令才能被CPU执行 - 伪的原因在于:对机器指令反汇编无法生成Go汇编,只能生成平台相关的汇编 2. 寄存器 - 通用寄存器 与AMD64机器的寄存器对应关系如下: 一般前六个用来传递参数,BP和SP用于管理栈顶和栈底

  34. 3.6 内存对齐historical

    1. 机器字长 1.1. 地址总线和数据总线 - CPU通过地址总线到内存中寻址,而内存通过数据总线把数据传输给CPU - 地址总线的位数决定了内存大小:比如8bit地址总线,那么可以寻址[0, 255]总共256B的内存,内存超过256B也利用不了 - 数据总线则决定了一次性能传输多少数据:比如要

  35. 3.7 GChistorical

    1. 什么是GC GC.md 2. 为什么需要GC GC.md 2.1. GC的问题 2.1.1. 内存泄露 Golang内存泄露.md 2.1.2. STW 通过三色标记法减少GC STW的时间 3. 如何进行垃圾回收 3.1. GC触发 - 主动触发 - 通过调用 runtime.GC 来触发

  36. 3.8 Golang栈管理historical

    1. 栈是什么 - 空间小,数据存放时间较短暂。栈在高地址,从高地址向低地址增长 - 分配:函数调用自动分配 - 回收:函数返回自动回收 2. Golang栈的特点 2.1. 动态扩容 - go runtime不是给每个goroutine分配固定的空间,而是需要的动态分配栈空间 - 创建gorout

  37. 3.9 Golang堆管理historical

    1. 堆是什么 - 空间大,数据存放时间较长。堆在低地址,从低地址向高地址增长 - 分配:程序员手动分配 - 回收:GC Go的内存管理是runtime,也就是说并不是每次内存分配都需要进行系统调用。 采用的算法是 TCMalloc 算法,即 Thread-Caching Malloc 。 他把可用

  38. 4.1 unittesthistorical

    1. 是什么 单元测试 2. 使用 - 文件名 xxx test.go - 导入 testing - 函数名必须 TestXXX - 运行 - go test . 3. 参考 - Go语言基础之单元测试 \ 李文周的博客 - testing \- The Go Programming Languag

  39. 4.2 pprofhistorical

    1. pprof是什么 Golang的性能分析工具。 2. 如何使用pprof 有两个库: runtime/pprof :采集工具型应用运行数据进行分析 net/http/pprof :采集web应用运行时数据进行分析 benchmark :压测 2.1. runtime/pprof 2.1.1.

  40. 4.3 benchmarkhistorical

    1. 使用 - bench.go - bench test.go - 测试: - go test -bench=. - 查看内存分配信息: go test -bench=. -benchmem - 生成CPU信息: go test -bench=. -benchmem -cpuprofile pro

  41. 4.4 Golang内存泄露historical

    1. 内存泄露 内存泄露.md 2. Golang内存泄露 2.1. root对象引用 2.2. goroutine 泄漏 goroutine泄露:原理、场景、检测和防范 \- SegmentFault 思否 - 如果你启动了一个 goroutine,但并没有符合预期的退出,那么直到程序结束这个go

  42. 4.5 tracehistorical

    1. 使用 步骤如下: 1. 导入包: import runtime/trace 2. 开启分析: trace.Start(file) 停止分析: trace.Stop() 3. 命令行分析 - go tool trace trace.out - 2. 参考 Go execution tracer