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都是引用类型,传递地址与传递“值”效果都是一样的