zoukankan      html  css  js  c++  java
  • go4

    go4

    引用循环
    package main
    const N=3
    
    func 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

    1566524831850

    最后没i++ 了,就等于3了 0x123

    正常输出
    package main
    const N=3
    
    func main(){
    	m := make(map[int]int)
    	for i:=0 ; i<N;i++{
    		m[i]=i
    	}
    	for _,v:= range m{
    		print(v)
    	}
    }
    

    --->012

    make() new()

    make() 创建切片,map,数组,通道

    new() 创建自定义对象

    make()会初始化,new()不会

    锁,for抛协程和函数正常传值
    const M = 10
    func 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或者10
    
    go的加载顺序

    main包-->const常量--->var变量--->init()--->main函数

    协程写入必须加锁

    const M1  = 10
    func 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)
    }
    
    

    --->

    false
    true
    
    map中结构体
    json反格式化到结构体小写取不到
    栈和堆的区别

    区别:

    栈:空间比较小 , 存储变量/函数参数等,编译器自动分配和释放

    堆:空间比较大, 一般有程序员分配和释放(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 
    ",f.Name,f.Type,val)
    
    
    	}
    	//获取方法
    	fmt.Println()
    	for i:= 0 ; i< t.NumField();i++{
    		m := t.Field(i)
    		fmt.Printf("%s:%v
    ",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:int
    Name:string
    Addr:string
    
    Hello: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
    ",t.Field(0))
    
       //  获取值
       v := reflect.ValueOf(u)
       fmt.Printf("%#v
    ",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

    goroutine
    • go并发设计的核心
    • 是协程
    创建

    go + 语句

    func newTask(){
    	i:= 0
    	for {
    		i++
    		fmt.Printf("newTask i=%d 
    ",i)
    		time.Sleep(1*time.Second)
    	}
    }
    func main(){
    	go newTask()
    
    
    	i:= 0
    	for {
    		i++
    		fmt.Printf("mainTask i=%d 
    ",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包

    runtime.Gosched()
    runtime.Goexit()
    runtime.GOMAXPROCS()

    runtime.Gosched()
    func newTask(){
       i:= 0
       for {
          i++
          fmt.Printf("newTask i=%d 
    ",i)
          time.Sleep(1*time.Second)
       }
    }
    func main(){
       go newTask()
       //go newTask()
    
       //i:= 0
       //for {
       // i++
       // fmt.Printf("mainTask i=%d 
    ",i)
       // time.Sleep(1*time.Second)
       //}
    
       // 阻塞, 睡眠 锁 解决
       for{}
    }
    
    //mainTask i=1
    //newTask i=1
    //mainTask i=2
    //newTask i=2
    //newTask i=3
    //mainTask i=3
    
    runtime.Goexit()
    func 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.defer
    
    runtime.GOMAXPROCS()
    func main()  {
       // 并行计算CPU核数
       runtime.GOMAXPROCS(1)   //11111111111111111111111111111
       //runtime.GOMAXPROCS(3)   //011001100110011100011001100110
    
       for {
          go fmt.Print(0)
          fmt.Print(1)
       }
    }
    
    channel 管道

    1566531335865

    传数据

    • 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取数据,并赋值给x
    x, 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
    
    
    无缓冲的channel
    • 无缓冲的通道是指在接收前没有能力保存任何值的通道

    ![2018-01-15_135129](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png)

    有缓冲的channel
    • 有缓冲的通道是一种在被接收前能存储一个或者多个值的通道

    ![2018-01-15_150701](file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png)

    放满了怎么办?

    func main(){
    	// 无缓冲通道
    	//c := make(chan int, 0)  //
    	// 有缓冲通道
    	c := make(chan int, 3)  // 缓冲3个
    	fmt.Printf("len(c)=%d,cap(c)=%d
    ",len(c),cap(c))
    	// 模拟两个人  子协程  存数据
    	go func() {
    		for i:=0 ; i<3 ; i++{
    			c <- i
    			fmt.Printf("子协程[%d]运行,len(c)=%d,cap(c)=%d
    ",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
    ",len(c),cap(c))
    	go func() {
    		for i:=0 ; i<10 ; i++{
    			c <- i
    			fmt.Printf("子协程[%d]运行,len(c)=%d,cap(c)=%d
    ",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
    ",i,len(c),cap(c))
    		}
    		close(c) //标识一下,没有了
    	}()
    

    ---> 关闭一下,就可以了

    单方向的channel
    var ch1 chan int   // 双向的
    var ch2 chan<- float64   单向通道,只用于存入数据,只写float64
    var 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
    //4
    
    
    定时器

    Timer : 时间到了,就执行,执行一次

    Ticker : 时间到了,就执行,执行多次

    func main()  {
    	time1 := time.NewTimer(time.Second*2)
    	//打印当前时间
    
    	fmt.Printf("当前时间:%v
    ",time.Now())
    
    	fmt.Printf("timer里的时间:%v
    ",<-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.012115101
    
    
    2. 只执行一次
    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.002057301
    goroutine 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)
    
    
  • 相关阅读:
    Hadoop集群(三) Hbase搭建
    Hadoop集群(二) HDFS搭建
    Hadoop集群(一) Zookeeper搭建
    Redis Cluster 添加/删除 完整折腾步骤
    Redis Cluster在线迁移
    Hadoop分布式HA的安装部署
    Describe the difference between repeater, bridge and router.
    what is the “handover” and "soft handover" in mobile communication system?
    The main roles of LTE eNodeB.
    The architecture of LTE network.
  • 原文地址:https://www.cnblogs.com/Doner/p/11399296.html
Copyright © 2011-2022 走看看