golangFamily
【超全golang面试题合集+golang学习指南+golang知识图谱+成长路线】 一份涵盖大部分golang程序员所需要掌握的核心知识。
脑图持续不断更新中,在线查看地址
后续文章和内容会不断更新到 github项目 中,欢迎关注。
目录(善用Ctrl+F)
-
基础入门
-
新手
-
数据类型
-
连nil切片和空切片一不一样都不清楚?那BAT面试官只好让你回去等通知了。
nil切片和空切片指向的地址不一样。nil空切片引用数组指针地址为0(无指向任何实际地址)
空切片的引用数组指针地址是有的,且固定为一个值
-
golang面试题:字符串转成byte数组,会发生内存拷贝吗?
字符串转成切片,会产生拷贝。严格来说,只要是发生类型强转都会发生内存拷贝。那么问题来了。
-
并不是,所有切片的大小相同;三个字段(一个 uintptr,两个int)。切片中的第一个字是指向切片底层数组的指针,这是切片的存储空间,第二个字段是切片的长度,第三个字段是容量。将一个 slice 变量分配给另一个变量只会复制三个机器字。所以 拷贝大切片跟小切片的代价应该是一样的。
type SliceHeader struct { Data uintptr Len int Cap int }
-
map不初始化使用会怎么样
panic: assignment to entry in nil map
-
map不初始化长度和初始化长度的区别
不初始化不能使用,长度为0;初始化若没有使用,长度也为0.
-
map承载多大,大了怎么办
扩容2^B
-
map的iterator是否安全?能不能一边delete一边遍历?
安全 可以
-
字符串不能改,那转成数组能改吗,怎么改
[]byte
-
怎么判断一个数组是否已经排序
-
普通map如何不用锁解决协程安全问题
-
array和slice的区别
-
数组定长,定义的时候就需要确定。切片长度不定,append时会自动扩容
-
相同大小数组可以赋值,会拷贝全部内容。slice赋值和指针一样。数组和slice之间不能相互赋值。当然slice有自己的copy函数
-
数组也可以进行切片,返回值是一个slice,改变slice时会同步修改数组内容,相当于取得了这个数组的指针
-
-
零切片、空切片、nil切片是什么 [连nil切片和空切片一不一样都不清楚?那BAT面试官只好让你回去等通知了。 - 知乎 (zhihu.com)]
var s1 []int // nil切片 s2 := make([]int,0) // 空切片 s4 := make([]int,0) // 空切片
-
slice深拷贝和浅拷贝
slice的浅拷贝就是指slice变量的赋值操作。
slice的深拷贝就是指使用内置的copy函数来拷贝两个slice。
-
map触发扩容的时机,满足什么条件时扩容?
2^B * 6.5 溢出的不算
-
map扩容策略是什么
-
自定义类型切片转字节切片和字节切片转回自动以类型切片
json
buffer
-
make和new什么区别
内置函数new按指定类型长度分配零值内存,返回指针,并不关心类型内部构造和初始化方式。
内置函数make对引用类型进行创建,编译器会将make转换为目标类型专用的创建函数,以确保完成全部内存分配和相关属性初始化。
*注意的点:*
1、new(T) 返回的是 T 的指针
new(T) 为一个 T 类型新值分配空间并将此空间初始化为 T 的零值,返回的是新值的地址,也就是 T 类型的指针 *T,该指针指向 T 的新分配的零值。
2、make 只能用于 slice,map,channel
make 只能用于 slice,map,channel 三种类型,make(T, args) 返回的是初始化之后的 T 类型的值,这个新值并不是 T 类型的零值,也不是指针 T,是经过***初始化之后的 T 的引用****。
-
slice ,map,chanel创建的时候的几个参数什么含义
-
线程安全的map怎么实现
-
-
流程控制
-
-
进阶
-
包管理
学go mod就够了! -
优化
-
[内存碎片化问题][Go内存分配机制总结 - 简书 (jianshu.com)
多级缓存cache、central、heap
-
chan相关的goroutine泄露的问题
chan不关闭会导致相关的goroutine无法释放
-
string相关的goroutine泄露的问题
获取长字符串中的一段导致长字符串未释放
-
获取长字符串中的一段导致长字符串未释放
同样,获取长slice中的一段导致长slice未释放
在长slice新建slice导致泄漏
goroutine泄漏
time.Ticker未关闭导致泄漏
Finalizer导致泄漏
Deferring Function Call导致泄漏
-
sync.Pool的适用场景[Go 并发编程 — 深入浅出 sync.Pool ,围观最全的使用姿势,理解最深刻的原理 (qq.com)]
-
go1.13sync.Pool对比go1.12版本优化点
优化锁竞争
-
并发编程
-
sync.map 的优缺点和使用场景
大量读,少量写
-
sync.Map的优化点
目前相当于表锁,可以行锁
-
高级特性
-
协程和线程的差别
-
垃圾回收的过程是怎么样的?
-
什么是写屏障、混合写屏障,如何实现?[https://mp.weixin.qq.com/s/5xjH-LJ53XiNm2sMNQZiGQ]
-
开源库里会有一些类似下面这种奇怪的用法:
var _ io.Writer = (*myWriter)(nil)
,是为什么?检查 *myWriter 类型是否实现了 io.Writer 接口
-
协程之间是怎么调度的
Golang管理协程时也必然会涉及到协程之间的切换:阻塞的协程被切换出去,可运行的协程被切换进来。我们在本章节就来仔细分析下协程如何切换。
TLS
thread local storage:
getg()
goget()用来获取当前线程正在执行的协程g。该协程g被存储在TLS中。
mcall()
mcall在golang需要进行协程切换时被调用,用来保存被切换出去协程的信息,并在当前线程的g0协程堆栈上执行新的函数。一般情况下,会在新函数中执行一次schedule()来挑选新的协程来运行。接下来我们就看看mcall的实现。
-
gc的stw是怎么回事
-
利用golang特性,设计一个QPS为500的服务器
sysn.pool
-
为什么gc会让程序变慢
stw,屏障,并行标记
-
开多个线程和开多个协程会有什么区别
多线程和协程之间的共同点和区别:
共同点:
都是并发操作,多线程同一时间点只能有一个线程在执行,协程同一时间点只能有一个任务在执行;
不同点:
多线程,是在I/O阻塞时通过切换线程来达到并发的效果,在什么情况下做线程切换是由操作系统来决定的,开发者不用操心,但会造成竞争条件 (race condition) ;
协程,只有一个线程,在I/O阻塞时通过在线程内切换任务来达到并发的效果,在什么情况下做任务切换是开发者决定的,不会有竞争条件 (race condition) 的情况;多线程的线程切换比协程的任务切换开销更大;对于开发者而言,多线程并发的代码比协程并发的更容易书写。
一般情况下协程并发的处理效率比多线程并发更高。
-
两个interface{} 能不能比较
总结一下:
1、判断类型是否一样reflect.TypeOf(a).Kind() == reflect.TypeOf(b).Kind()
2、判断两个interface{}是否相等
reflect.DeepEqual(a, b interface{})
3、将一个interface{}赋值给另一个interface{}
reflect.ValueOf(a).Elem().Set(reflect.ValueOf(b))
-
必须要手动对齐内存的情况
-
golang怎么做代码优化
-
问题排查
-
源码阅读
-
汇编
-
实践常用工具
-
-
图解网络基础
-
骚话连篇
-
包
- 常用官方包说明
- 常用第三方包说明
- 常用框架
- 完整标准库列表
- 优秀的第三方库
- 音频和音乐
- 数据结构:Go中的通用数据结构和算法
- 分布式系统:Go中的通用数据结构和算法
- 电子邮件:实现电子邮件创建和发送的库和工具
- 嵌入式脚本语言:在go代码中嵌入其他语言
- 错误处理
- 处理文件和文件系统的库
- 金融:会计和财务软件包
- 游戏开发:游戏开发相关库
- 地理位置:地理相关的位置信息和工具库
- 编译器相关:转到其他语言
- Goroutines:用于管理和使用Goroutines的工具
- 图形界面:用于构建GUI应用程序的库
- 图片:用于处理图像的库
- 物联网:物联网设备编程库
- JSON格式:用于处理JSON的库
- 机器学习:常用机器学习库
- 微软办公软件
- 自然语言处理
- 网络:与网络各层配合使用的库
- 视频:用于处理视频的库
- 其他
- 常用包
常用包 | 说明 |
---|---|
fmt | 实现格式化的输入输出操作,其中的fmt.Printf()和fmt.Println()是开发者使用最为频繁的函数。 |
io | 实现了一系列非平台相关的IO相关接口和实现,比如提供了对os中系统相关的IO功能的封装。我们在进行流式读写(比如读写文件)时,通常会用到该包。 |
bufio | 它在io的基础上提供了缓存功能。在具备了缓存功能后, bufio可以比较方便地提供ReadLine之类的操作。 |
strconv | 提供字符串与基本数据类型互转的能力。 |
os | 本包提供了对操作系统功能的非平台相关访问接口。接口为Unix风格。提供的功能包括文件操作、进程管理、信号和用户账号等。 |
sync | 它提供了基本的同步原语。在多个goroutine访问共享资源的时候,需要使用sync中提供的锁机制。 |
flag | 它提供命令行参数的规则定义和传入参数解析的功能。绝大部分的命令行程序都需要用到这个包。 |
encoding/json | JSON目前广泛用做网络程序中的通信格式。本包提供了对JSON的基本支持,比如从一个对象序列化为JSON字符串,或者从JSON字符串反序列化出一个具体的对象等。 |
http | 通过http包,只需要数行代码,即可实现一个爬虫或者一个Web服务器,这在传统语言中是无法想象的。 |
- 常用第三方包
| 包 | 地址 |
|:---------😐:------😐
|数据库操作 | github.com/jinzhu/gorm github.com/go-xorm/xorm |
|搜索es | github.com/olivere/elastic |
|rocketmq操作 | github.com/apache/rocketmq-client-go/v2 |
|rabbitmq 操作 | github.com/streadway/amqp |
|redis 操作 | github.com/go-redis/redis |
|etcd 操作 | github.com/coreos/etcd/clientv3 |
|kafka| https://github.com/Shopify/sarama https://github.com/bsm/sarama-cluster |
|excel 操作 | github.com/360EntSecGroup-Skylar/excelize |
|ppt 操作 | golang.org/x/tools/cmd/present |
|go-svg 操作 | https://github.com/ajstarks/svgo |
|go 布隆过滤器实现 | https://github.com/AndreasBriese/bbloom |
|json相关 | https://github.com/bitly/go-simplejson |
|LRU Cache实现 | https://github.com/bluele/gcache https://github.com/hashicorp/golang-lru |
|go运行时函数替换 | https://github.com/bouk/monkey |
|toml | https://github.com/toml-lang/toml https://github.com/naoina/toml |
|yaml | https://github.com/go-yaml/yaml |
|viper | https://github.com/spf13/viper |
|go key/value存储 | https://github.com/etcd-io/bbolt |
|基于ringbuffer的无锁golang workpool | https://github.com/Dai0522/workpool |
|轻量级的协程池 | https://github.com/ivpusic/grpool |
|打印go的详细数据结构 | https://github.com/davecgh/go-spew |
|基于ringbuffer实现的队列 | https://github.com/eapache/queue |
|拼音 | https://github.com/go-ego/gpy |
|分词 | https://github.com/go-ego/gse |
|搜索 | https://github.com/go-ego/riot |
|windows COM | https://github.com/go-ego/cedar |
|session | https://github.com/gorilla/sessions |
|路由 | https://github.com/gorilla/mux |
|websocket | https://github.com/gorilla/websocket |
|Action handler | https://github.com/gorilla/handlers |
|csrf | https://github.com/gorilla/csrf |
|context | https://github.com/gorilla/context |
|过滤html标