发布时间:2025-12-09 12:01:19 浏览次数:1
package mainconst N=3func main(){ m := make(map[int]*int) for i:=0 ; i<N;i++{ m[i]=&i } for _,v:= range m{ print(*v) }}0 = 0 -> 2
1 = 1 -> 2
2 = 2 -> 2
0 = 0 -> 3
1 = 1 -> 3
2 = 2 -> 3
----> 333
最后没i++ 了,就等于3了 0x123
package mainconst N=3func main(){ m := make(map[int]int) for i:=0 ; i<N;i++{ m[i]=i } for _,v:= range m{ print(v) }}--->012
make() 创建切片,map,数组,通道
new() 创建自定义对象
make()会初始化,new()不会
const M = 10func main(){ m := make(map[int]int) wg := &sync.WaitGroup{} mu := &sync.Mutex{} wg.Add(M) for i:=0 ; i< M;i++{ //go func(){ //go 抛协程 for 生成不同的新值 go func(i int){ // 正常 10 defer wg.Done() mu.Lock() m[i] = i mu.Unlock() }(i) } wg.Wait() println(len(m))}//1或者10main包-->const常量--->var变量--->init()--->main函数
协程写入必须加锁
const M1 = 10func main(){ m1 := make(map[int]int) wg1:= &sync.WaitGroup{} //flag := &sync.Mutex{} wg1.Add(M1) for i:=0 ; i< M1;i++{ go func(){ defer wg1.Done() //flag.Lock() m1[rand.Int()] = rand.Int() //flag.Unlock() }() } wg1.Wait() println(len(m1))}type S struct { a,b,c string}func main(){ x := interface{}(&S{"a","b","c"}) y := interface{}(&S{"a","b","c"}) fmt.Println(x==y) x1 := interface{}(S{"a","b","c"}) y1 := interface{}(S{"a","b","c"}) fmt.Println(x1==y1)}--->
falsetrue区别:
栈:空间比较小 , 存储变量/函数参数等,编译器自动分配和释放
堆:空间比较大, 一般有程序员分配和释放(java和Python垃圾回收自动处理,c需要处理内存) 存储数据
分配栈上 : a := xx var b = .. //前面放栈后面放堆
分配堆上 : new()大多数情况分配到堆上
type User struct { Id int Name string Addr string}func (u User)Hello(){ fmt.Println("hello")}//反射操作func Info(o interface{}){ //获取类型信息 t := reflect.TypeOf(o) fmt.Println("类型是:",t.Name()) //封装的直接返回类型 //获取值 v := reflect.ValueOf(o) fmt.Println("值是:",v) // 获取对象字段信息 fmt.Println() //t.NumField() 获取字段的数量,决定循环次数 for i:= 0; i<t.NumField();i++ { // 通过索引,取每个字段 f := t.Field(i) // Interface() : 可以去到字段对应的值 val := v.Field(i).Interface() fmt.Printf("%s:%v = %v \n",f.Name,f.Type,val) } //获取方法 fmt.Println() for i:= 0 ; i< t.NumField();i++{ m := t.Field(i) fmt.Printf("%s:%v\n",m.Name,m.Type) }}func main(){ u:=User{1,"zs","bj"} Info(u)}--->
类型是: User值是: {1 zs bj}Id:int = 1 Name:string = zs Addr:string = bj Id:intName:stringAddr:stringHello:func(main.User)type User struct { Id int Name string Addr string}type Boy struct { User Hobby string}func (u User)Hello(){ fmt.Println("hello")}func main(){ u:=Boy{User{1,"zs","bj"},"aa"} t:= reflect.TypeOf(u) // Anonymous 是true,则是匿名字段 // %#:获取详细信息 fmt.Printf("%#v\n",t.Field(0)) // 获取值 v := reflect.ValueOf(u) fmt.Printf("%#v\n",v.Field(0))}// 反射获得匿名变量//reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x4b8160), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true}//main.User{Id:1, Name:"zs", Addr:"bj"}func main(){ abc := 123 //abc = 222 // 编码时修改 v := reflect.ValueOf(&abc) v.Elem().SetInt(3432) // api fmt.Println("abc",abc) // abc 3432 运行时修改}// 反射操作修改一个结构体的值func setValue(o interface{}){ v := reflect.ValueOf(o) // 获取指针指向的真正的元素 v = v.Elem() f := v.FieldByName("Id") // Kind() 可以判断类型 if f.Kind() == reflect.Int{ f.SetInt(222) }}func main(){ u:= User1{1,"z","bj"} setValue(&u) fmt.Println(u) }--->{222 z bj}
func (u User1) Hello(){ fmt.Println("hello")}//func (u User1) Hello(name string){// fmt.Println("hello",name)//}func main(){ u:= User1{1,"z","bj"} v := reflect.ValueOf(u) m := v.MethodByName("Hello") args := []reflect.Value{} //args := []reflect.Value{11} // 带参数的 //m.Call(args) //直接调用 hello m.Call(args)} java的并发也不好,老语言
c语言 并发好 , go 稍微差一点,天然支持高并发,不用代码层次
处理高并发
没有高并行:加机器
老公司,懒得转语言了,即使不快
新公司,都是go
go + 语句
func newTask(){ i:= 0 for { i++ fmt.Printf("newTask i=%d \n",i) time.Sleep(1*time.Second) }}func main(){ go newTask() i:= 0 for { i++ fmt.Printf("mainTask i=%d \n",i) time.Sleep(1*time.Second) }}--->
//mainTask i=1//newTask i=1//mainTask i=2//newTask i=2//newTask i=3//mainTask i=3同时跑,主协程结束了,子协程还没跑到
解决:
// 阻塞, 睡眠 锁 解决 for{}runtime.Gosched()
runtime.Goexit()
runtime.GOMAXPROCS()
func newTask(){ i:= 0 for { i++ fmt.Printf("newTask i=%d \n",i) time.Sleep(1*time.Second) }}func main(){ go newTask() //go newTask() //i:= 0 //for { // i++ // fmt.Printf("mainTask i=%d \n",i) // time.Sleep(1*time.Second) //} // 阻塞, 睡眠 锁 解决 for{}}//mainTask i=1//newTask i=1//mainTask i=2//newTask i=2//newTask i=3//mainTask i=3func main() { go func() { defer fmt.Println("A.defer") // 匿名函数 func(){ defer fmt.Println("B.defer") // 结束当前协程 runtime.Goexit() //B.defer A.defer 不走之后的了,然后最后延时 fmt.Println("B") }() fmt.Println("A") }() for{}}// 不退出版//B//B.defer//A//A.deferfunc main() { // 并行计算CPU核数 runtime.GOMAXPROCS(1) //11111111111111111111111111111 //runtime.GOMAXPROCS(3) //011001100110011100011001100110 for { go fmt.Print(0) fmt.Print(1) }}传数据
channel可以用内置make()函数创建
定义一个channel时,也需要定义发送到channel的值的类型
make(**chan** 类型) make(**chan** 类型, 容量) 当 capacity= 0 时,channel 是无缓冲阻塞读写的,当capacity> 0 时,channel 有缓冲、是非阻塞的,直到写满 capacity个元素才阻塞写入
channel通过操作符<-来接收和发送数据,发送和接收数据语法:
channel <- value // 发送vlaue到channel<-channel // 从channel取数据,并丢弃x := <-channel // 从channel取数据,并赋值给xx, ok := <-channel // 功能同上,检查通道是否关闭,是否为空代码
func main(){ // 创建管道 c := make(chan int) // 只能传int的 // 子协程存入数据到管道 go func(){ defer fmt.Println("111") fmt.Println("222") // 向管道发送数据 c <- 123 }() // 主协程从管道取数据 num := <-c fmt.Println("num = ",num) fmt.Println("over")}//222//111//num = 123//over放满了怎么办?
func main(){ // 无缓冲通道 //c := make(chan int, 0) // // 有缓冲通道 c := make(chan int, 3) // 缓冲3个 fmt.Printf("len(c)=%d,cap(c)=%d\n",len(c),cap(c)) // 模拟两个人 子协程 存数据 go func() { for i:=0 ; i<3 ; i++{ c <- i fmt.Printf("子协程[%d]运行,len(c)=%d,cap(c)=%d\n",i,len(c),cap(c)) } }() // 主协程 取数据 time.Sleep(2*time.Second) // 睡,没有接数据,有接就发了 for i:=0 ; i<3 ; i++{ num := <- c fmt.Println("num=",num) }}//len(c)=0,cap(c)=0 //在这里等待//num= 0//子协程[0]运行,len(c)=0,cap(c)=0//子协程[1]运行,len(c)=0,cap(c)=0//num= 1//num= 2//有缓冲//len(c)=0,cap(c)=3//子协程[0]运行,len(c)=1,cap(c)=3//子协程[1]运行,len(c)=2,cap(c)=3//子协程[2]运行,len(c)=3,cap(c)=3// 延时了 ,再接了//num= 0//num= 1//num= 2如果缓冲设置小了,那么缓冲小的,就是有缓冲,
其他的是走无缓冲,先走主协程,等待等等
通道里数据少了,取多的,报错了
func main(){ c := make(chan int, 3) // 缓冲3个 fmt.Printf("len(c)=%d,cap(c)=%d\n",len(c),cap(c)) go func() { for i:=0 ; i<10 ; i++{ c <- i fmt.Printf("子协程[%d]运行,len(c)=%d,cap(c)=%d\n",i,len(c),cap(c)) } }() // 主协程 取数据 for { if val,ok := <- c;ok{ fmt.Println(val) }else{ break } } fmt.Println("结束了")}---->错误显示
///...//7//8//9//fatal error: all goroutines are asleep - deadlock!// goroutine 1 [chan receive]: go func() { for i:=0 ; i<10 ; i++{ c <- i fmt.Printf("子协程[%d]运行,len(c)=%d,cap(c)=%d\n",i,len(c),cap(c)) } close(c) //标识一下,没有了 }()---> 关闭一下,就可以了
var ch1 chan int // 双向的var ch2 chan<- float64 单向通道,只用于存入数据,只写float64var ch3 <-chan int //取数据func main(){ //通道 c := make(chan int ,5) //转换为只写的通道 var send chan <- int = c //转换为只读的通道 var recv <- chan int = c send <- 123 fmt.Println("<-recv",<-recv) // <-recv 123}生产者和消费者模型(和后台的关系)
// 创建生产者func producter(out chan<-int ) { defer close(out) // 可以改数据 for i:= 0; i<5;i++{ out <-i }}// 创建消费者func consumer(in <-chan int) { // 用于查找东西 无法改数据,迭代的是range for x:= range in { fmt.Println(x) }}func main() { c:=make(chan int,10) go producter(c) consumer(c) for {}}//0//1//2//3//4Timer : 时间到了,就执行,执行一次
Ticker : 时间到了,就执行,执行多次
func main() { time1 := time.NewTimer(time.Second*2) //打印当前时间 fmt.Printf("当前时间:%v\n",time.Now()) fmt.Printf("timer里的时间:%v\n",<-time1.C)}//当前时间:2019-08-23 12:27:13.7582115 +0800 CST m=+0.002000201//timer里的时间:2019-08-23 12:27:15.7683264 +0800 CST m=+2.0121151012. 只执行一次time2:=time.NewTimer(time.Second*1)for{ //<-time2.C c:=<-time2.C //fmt.Println("xxx") fmt.Println(c)}fatal error: all goroutines are asleep - deadlock!2019-08-23 12:29:45.3538822 +0800 CST m=+1.002057301goroutine 1 [chan receive]:main.main() //3.停止定时器 time3:=time.NewTimer(time.Second*2) go func() { <-time3.C fmt.Println("时间到") }() stop:=time3.Stop() if stop{fmt.Println("3已关闭")} //3已关闭time4:=time.NewTimer(time.Second*2) time4.Reset(3*time.Second) fmt.Println(<-time4.C)