golang 坑集

func main() {
	x := 1
	defer func(a int) { fmt.Println("a=",a) }(x)
	defer func() { fmt.Println("x=",x) }()
	x++
}

结果:x=2a=1

说明:defer 调用所需参数在 defer 语句执行时就被已计算好了 (拷贝传递),闭包内则是引用,defer执行顺序FIFO

数组和slice

数组是值类型 slice是引用类型,

数组的创建 arr:=[...]int{1,2,3} arr:=[3]int{} arr:=new([10]int) (注意new返回的是[10]int的指针类)

slice的创建 slice:=[]int{1,3} slice:=arr[n:m]( n <= x < m) slice:=make([]int,len,[cap]) (cap default=len)

每个slice指向了一个底层数组,对slice的更新会反映到这个底层数组上,cap=slice在数组的start_index到数组的end_index

reslice slice1:=slice2[n:m] 在slice进行reslice时如果n,m超过了cap 不会引发底层数组的重分配 ,而会panic: runtime error: index out of range

append(s1,1,3) 可以引发底层数组重分配 增加一个cap

copy(dst,src) len=min(len(dst),len(src))

map

d := map[*int]struct{ x,y float64 } { &10: { 1.0,2.0 } }


struct 和数组一样 也是值类型

type s1 struct {
	s2 struct {
		a int
	}
}
func main() {
	m := map[int]struct{ a int }{1: {1}}//正确
	fmt.Println(m)
	
	s := s1{{1}}//异常 missing type in composite literal
	fmt.Println(s)
}
匿名struct可以作为map的value而且赋值方便,而匿名struct作为struct的成员则在初始化时 需要带上struct的名字才行,成员变量 匿名struct 就不方便了。

struct拷贝复制

u := User{ 100,"Tom" }
var u2 *User = new(User)
*u2 = u


匿名成员 (组合优于继承)

type D1 struct {
	x int
}
type Data struct {
	D1
	x int
}

func main() {
	d := Data{D1{10},20}
	d.x = 200
	d.D1.x = 100
	fmt.Println(d)
}


接口类型推断

if o,ok:=i.(User);ok{ o.xxx } switch o:=i.(type){ case User: xxx case Man: xxx }

将对象赋值给接口变量时,会发发生值拷贝行为

u := User{ 1,"Tom" }
i := Tester(u)//强制转换 赋值发生的是copy动作
//在golang里要千万注意 = 这个赋值动作 都是copy动作,如果copy的对象是个指针的话性能会比较好
u.Id = 100 // 显式修改的原对象
u.Name = "Jack"
fmt.Println(u,i) // 虽然接⼝口内的复制品未受到影响

相关文章

程序目录结构 简单实现,用户登录后返回一个jwt的token,下次请求带上token请求用户信息接口并返回信息...
本篇博客的主要内容是用go写一个简单的Proof-of-Work共识机制,不涉及到网络通信环节,只是一个本地的简...
简介 默克尔树(MerkleTree)是一种典型的二叉树结构,其主要特点为: 最下面的叶节点包含存储数据或其...
接下来学习并发编程, 并发编程是go语言最有特色的地方, go对并发编程是原生支持. goroutine是go中最近本...
先普及一下, 什么是广度优先搜索 广度优先搜索类似于树的层次遍历。从图中的某一顶点出发,遍历每一个顶...
第一天: 接口的定义和实现 第二天: 一. go语言是面向接口编程. 在学习继承的时候说过, go语言只有封装,...