小心指针的陷阱



name=tomname=jackjack

struct赋值的顺序


age虽然在name之前,但是因为name是函数fmt.Sprintf的返回值,所以在初始化user的时候,会先处理成员变量是表达式的返回值的。

defer panic return的顺序


do something->do defer->panic


do something->do defer->return

json number反射到interface的坑


json number反射到interface上,这时通过断言为int是错误的,此时interface断言是float64。

小心for循环临时变量和goroutine组合的坑


i是临时变量,当每个goroutine抢着去打印i的时候,其结果是不确定的,每个gourotine运行到的时候,i当前是什么,就打印什么。

range一个chan的时候,记得在close,不然会deadlock



map是要初始化的,不然会报nil map



从map中取不存在key的时候,返回的是对应的零值


if v,ok := x["two"]; ok

byte和rune傻傻分不清楚


byte表示字节,一个中文正常3个字节,rune用来表示Unicode的码点,即一个字符。

代码块内同名变量的修改,不会影响代码块外的值



range map是无序的



nil != nil


{nil,nil}{*int,nil}

小心你的类型溢出


for{}

给一个已经close的channel发数据会panic



从一个已经close的channel收数据会收到零值



通过context timeout来控制超时



make和new的区别


通过定义可以看出new返回的是指针,make返回的类型的值。make可以是slice、map和chan,new可以new一个类型。

append扩容导致的底层数组的变化


最后一次append,原数组容量不够,重新分配数组。地址变化。

go抢占式调度


在只有一个处理器的情况下,即使一个goroutine是死循环,它也不会一直执行下去

select的随机性



无缓冲和有缓冲的chan的区别


无缓冲的chan,是同步阻塞的,必须存在某个时刻,在写的同时,另一个已经在准备接收了。带缓冲的chan,在缓冲区没满的时候,是不阻塞的。

... 来接收可变长参数



尽量使用小内存字段


根据所需,选择合理的类型,对GC友好。

空struct不占空间



两个无符号的数字最好不要相减,不会得到负数



go的strcut是可以比较的



map、slice、func不可比较,除非是nil



注意close你的http body,防止内存泄露



注册recover,防止panic导致的程序意外退出



go 语句后面的函数调用,其参数会先求值


所以以上会deadlock