map的无序性
大量数据如果没有写入,只是读取不会出错
var wg sync.WaitGroup
m := make(map[int]int)
for i := 0; i < 10000; i++ {
m[i] = i
}
wg.Add(100000)
for i := 0; i < 10; i++ {
go func() {
for v, k := range m {
fmt.Printf("第%d个go程 key:%v-value:%v\n", i, v, k)
wg.Done()
}
}()
}
wg.Wait()
//执行结果 无序
//...
//第10个go程 key:7410-value:7410
//第10个go程 key:2710-value:2710
//第10个go程 key:5388-value:5388
//第10个go程 key:9667-value:9667
//第10个go程 key:477-value:477
//第10个go程 key:579-value:579
//第10个go程 key:3405-value:3405
顺带一个map引用传递的问题,其实传值或者传地址,都没有发生拷贝
传递的其实是map的引用,没有发生拷贝
var wg sync.WaitGroup
m := make(map[int]int)
for i := 0; i < 3; i++ {
m[i] = i
}
fmt.Printf("map全局地址:%p\n",m)
wg.Add(2)
for i := 0; i < 2; i++ {
go func(i int,m1 map[int]int) {
for v, k := range m1 {
fmt.Printf("第%d个go程 key:%v-value:%v\n", i, v, k)
//wg.Done()
}
fmt.Printf("map全局地址:%p\n,map局部变量地址%p\n", m, m1)
wg.Done()
}(i,m)
}
wg.Wait()
//map全局地址:0xc000071bc0
//第1个go程 key:0-value:0
//第1个go程 key:1-value:1
//第1个go程 key:2-value:2
//map全局地址:0xc000071bc0
//,map局部变量地址0xc000071bc0
//第0个go程 key:0-value:0
//第0个go程 key:1-value:1
//第0个go程 key:2-value:2
//map全局地址:0xc000071bc0
//,map局部变量地址0xc000071bc0
map引用传递
var wg sync.WaitGroup
m := make(map[int]int)
for i := 0; i < 3; i++ {
m[i] = i
}
fmt.Printf("map全局地址:%p\n",m)
wg.Add(2)
for i := 0; i < 2; i++ {
go func(i int,m1 *map[int]int) {
for v, k := range *m1 {
fmt.Printf("第%d个go程 key:%v-value:%v\n", i, v, k)
//wg.Done()
}
fmt.Printf("map全局地址:%p\n,map局部变量地址%p\n", m, *m1)
wg.Done()
}(i,&m)
}
wg.Wait()
//map全局地址:0xc000202b40
//第1个go程 key:0-value:0
//第1个go程 key:1-value:1
//第1个go程 key:2-value:2
//map全局地址:0xc000202b40
//,map局部变量地址0xc000202b40
//第0个go程 key:0-value:0
//第0个go程 key:1-value:1
//第0个go程 key:2-value:2
//map全局地址:0xc000202b40
//,map局部变量地址0xc000202b40
slice是有序的
这里有个疑问,为什么切片不用引用传递
var wg sync.WaitGroup
s := make([]int, 3)
for i := 0; i < len(s); i++ {
s[i] = i
}
fmt.Printf("slice全局地址:%p\n",s)
wg.Add(2)
for i := 0; i < 2; i++ {
go func(i int,) {
for v, k := range s {
fmt.Printf("第%d个go程 key:%v-value:%v\n", i, v, k)
}
fmt.Printf("slice go程里面地址%p\n", s)
wg.Done()
}(i)
}
wg.Wait()
//slice全局地址:0xc000010860
//第1个go程 key:0-value:0
//第1个go程 key:1-value:1
//第1个go程 key:2-value:2
//slice go程里面地址0xc000010860
//第0个go程 key:0-value:0
//第0个go程 key:1-value:1
//第0个go程 key:2-value:2
//slice go程里面地址0xc000010860
var wg sync.WaitGroup
s := make([]int, 3)
for i := 0; i < len(s); i++ {
s[i] = i
}
fmt.Printf("slice全局地址:%p\n",s)
wg.Add(2)
for i := 0; i < 2; i++ {
go func(i int, s1 []int) {
for v, k := range s1 {
fmt.Printf("第%d个go程 key:%v-value:%v\n", i, v, k)
}
fmt.Printf("slice全局地址:%p\n,slice局部变量地址%p\n", s, s1)
wg.Done()
}(i, s)
}
wg.Wait()
//slice全局地址:0xc000208080
//第1个go程 key:0-value:0
//第1个go程 key:1-value:1
//第1个go程 key:2-value:2
//slice全局地址:0xc000208080
//,slice局部变量地址0xc000208080
//第0个go程 key:0-value:0
//第0个go程 key:1-value:1
//第0个go程 key:2-value:2
//slice全局地址:0xc000208080
//,slice局部变量地址0xc000208080
var wg sync.WaitGroup
s := make([]int, 3)
for i := 0; i < len(s); i++ {
s[i] = i
}
fmt.Printf("slice全局地址:%p\n",s)
wg.Add(2)
for i := 0; i < 2; i++ {
go func(i int, s1 *[]int) {
for v, k := range *s1 {
fmt.Printf("第%d个go程 key:%v-value:%v\n", i, v, k)
}
fmt.Printf("slice全局地址:%p\n,slice局部变量地址%p\n", s, *s1)
wg.Done()
}(i, &s)
}
wg.Wait()
//slice全局地址:0xc00019a060
//第0个go程 key:0-value:0
//第0个go程 key:1-value:1
//第0个go程 key:2-value:2
//slice全局地址:0xc00019a060
//,slice局部变量地址0xc00019a060
//第1个go程 key:0-value:0
//第1个go程 key:1-value:1
//第1个go程 key:2-value:2
//slice全局地址:0xc00019a060
//,slice局部变量地址0xc00019a060
结论:
1、并发读取如果中间没有写等操作,读取是没有问题的
2、map、slice都是引用类型,传递地址与传递“值”效果都是一样的