• go的接口,并发和并行,协程,信道,缓冲处理,异常处理


    //指针 结构体  方法
    
    //1 指针:(地址)
    	-什么类型的指针,就是在类型前加 *
    	-取什么变量的地址,就是在变量前加 &
    	-通过指针得到值(解引用),在变量前加*
    	
    	-当参数传递,修改会影响原来的值
    	-一般情况下,引用不需要再去地址了,取地址一般取值类型的地址
    //2 结构体
    	-面向对象当中的类,只有属性 ,没有方法(一系列属性的集合)
    		type Person struct{ 一堆属性}
    	-使用结构体:a:=Person{} 按位置,按关键字传参
    	-取值: . 取值
    	-结构体是值类型,默认是是属性的默认值
    	-匿名结构体
    	-匿名字段
    	-结构体嵌套(变量提升)
    	-结构体比较(如果结构体中有引用类型,不支持比较)
    //3 方法(特殊的函数)
    	-func关键字和函数名之间有个特殊类型接收器
    		-func (a 结构体名字)方法名(参数)(返回值){}
    	-绑定给结构体,结构体通过 . 方式来调用
    	-值接收器和指针接收器(值接收器不会修改原来的,指针接收器会修改原来的)
    	-不论值还是指针,都可以直接调用方法(值接收器类型,指针接收器类型)
    	-匿名字段的方法(方法提升,类似于面向对象中的继承,多继承)
    	-非结构体上绑定方法(自己定义的属性)
    	
    
    
    //go的指针,结构体,匿名结构体,匿名字段,信道,缓冲信道,方法,函数,接口,goroutine,闭包函数,匿名函数
    
    

    1 接口

    //一系列方法的集合,规范了子类的行为,    
    	-python和go都属于鸭子类型,非侵入式接口
    	-java:侵入式接口
    package main
    
    import "fmt"
    
    //1 定义一个接口,(规范行为,没有具体实现)
    type DuckInterface interface {
    	Run()
    	Speak()
    }
    
    //定义一个TDuck结构体
    type TDuck struct {
    	name string
    	age int
    	wife string
    }
    //TDuck实现接口(实现接口中的所有方法)
    func (t TDuck)Run()  {
    	fmt.Println("我是唐老鸭,我的名字是",t.name,"我说人话")
    }
    func (t TDuck)Speak()  {
    	fmt.Println("我是唐老鸭,我的名字是",t.name,"我学人走路")
    }
    
    //定义一个RDuck结构体
    type RDuck struct {
    	name string
    	age int
    }
    //RDuck实现接口(实现接口中的所有方法)
    func (t RDuck)Run()  {
    	fmt.Println("我是普通肉鸭,我的名字是",t.name,"我阿嘎嘎叫")
    }
    func (t RDuck)Speak()  {
    	fmt.Println("我是普通肉鸭,我的名字是",t.name,"我歪歪扭扭走路")
    }
    
    
    // 5 有名空接口
    type EmptyInterface interface {
    
    }
    
    func main() {
    	//2 实例化得到TDuck和RDuck两个对象
    	//t:=TDuck{"鸡哥",88,"凤姐"}
    	r:=RDuck{"普通鸭子",2}
    	//t.Run()
    	//t.Speak()
    	//r.Run()
    	//r.Speak()
    	//接口也是一个类型(可以定义一个变量是接口类型)
    	// 同一类事物的多种形态
    	//var d DuckInterface
    	//d=t
    	////d=r
    	//d.Speak()
    	//d.Run()
    	//想再去t的属性,name,age,wife
    	//test(t)
    	//test(r)
    
    
    	// 5 空接口
    	//-只要一个类型,实现接口所有的方法,就叫实现该接口
    	//-如果一个接口是空的,一个方法都没有,所有类型都实现了空接口
    	//-任意类型,都可以赋值给空接口类型
    	//var a EmptyInterface
    	//a=1
    	//a="xx"
    	//a=[3]int{1,2,3}
    
    	//6 接口类型空值(nil)
    	//var a EmptyInterface
    	//fmt.Println(a)
    
    	//7 匿名空接口
    	// interface{}
    	test(1)
    	test(r)
    	test(1.2)
    
    
    
    }
    
    ////3 类型断言
    //func test(d DuckInterface)  {
    //	//d.Run()
    //	//d.Speak()
    //	//var t TDuck
    //	//t=d.(TDuck)
    //	t:=d.(TDuck) //断言d是TDuck类型,如果正确,就会把d转成t
    //	fmt.Println(t.name)
    //	fmt.Println(t.wife)
    //	t.Speak()
    //	t.Run()
    //}
    
    //4 类型选择
    //func test(d DuckInterface)  {
    //	switch a:=d.(type) {
    //	case TDuck:
    //		fmt.Println(a.wife)
    //		fmt.Println("你是TDuck类型")
    //	case RDuck:
    //		fmt.Println(a.name)
    //		fmt.Println("你是RDuck类型")
    //	default:
    //		fmt.Println("不知道是什么类型")
    //	}
    //}
    
    //7 匿名空接口
    //func test(i interface{})  {
    func test(i EmptyInterface)  {
    	fmt.Println(i)
    }
    	
    
    package main
    
    // 1 实现多个接口
    //type DuckInterface1 interface {
    //	Run()
    //	Speak()
    //}
    //
    //type HumanInterface interface {
    //	Drive()
    //}
    //
    ////定义一个TDuck结构体
    //type TDuck1 struct {
    //	name string
    //	age int
    //	wife string
    //}
    ////TDuck实现接口(实现接口中的所有方法)
    //func (t TDuck1)Run()  {
    //	fmt.Println("我是唐老鸭,我的名字是",t.name,"我说人话")
    //}
    //func (t TDuck1)Speak()  {
    //	fmt.Println("我是唐老鸭,我的名字是",t.name,"我学人走路")
    //}
    ////实现HumanInterface接口
    //func (t TDuck1)Drive()  {
    //	fmt.Println("我是唐老鸭,我开车")
    //}
    
    // 2 接口嵌套
    type DuckInterface1 interface {
    	Run()
    	Speak()
    }
    
    type HumanInterface interface {
    	DuckInterface1
    	//相当于
    	//Run()
    	//Speak()
    	Drive()
    }
    
    func main() {
    	//t:=TDuck1{"鸡哥",18,"凤姐"}
    	//var d DuckInterface1
    	//var h HumanInterface
    	//d=t
    	//d.Run()
    	//d.Speak()
    	//h=t
    	//h.Drive()
    
    }
    

    2 并发和并行

    //并发:假如在他晨跑时,鞋带突然松了。于是他停下来,系一下鞋带,接下来继续跑
    //并行:如这个人在慢跑时,还在用他的 iPod 听着音乐
    
    
    

    3 go协程

    //go协程--》goroutine,并不是真正的协程(线程+协程,语言层面处理了,不需要开发者去关注)
    
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func hello()  {
    	fmt.Println("go go go!")
    }
    func main() {
    	fmt.Println("主函数开始")
    	go hello() //通过go关键字,开启goroutine,并发执行
    	go hello()
    	go hello()
    	go hello()
    
    	fmt.Println("主函数结束")
    	time.Sleep(2*time.Second)
    
    }
    
    

    4 信道

    //goroutine直接通信
    //go语言不推崇共享变量方法做通信,而推崇管道通信channel(信道)
    // 信道(管道)
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    func main() {
    	//1 信道也是一个变量(需要指明运输的类型)
    	//var a chan int //定义一个int类型信道
    
    	//2 信道的0值,nil类型,它是一个引用
    	//fmt.Println(a)
    
    	//3 信道初始化
    	//var a chan int=make(chan int)
    	//fmt.Println(a)
    
    	//4 信道的放值,和取值
    	//var a chan int=make(chan int)
    	//a<-1   //放值,把1放到信道中
    	////var b int=<-a    //取值
    	//<-a    //取值
    
    	//5 默认情况下,信道的放值和取值都是阻塞的(一次一个都放不进去)
    	fmt.Println("开始")
    	var a chan bool=make(chan bool)
    	//信道是引用类型
    	go hello1(a)
    
    	<-a
    	time.Sleep(2*time.Second)
    
    
    
    }
    
    func hello1(a chan bool)  {
    	fmt.Println("go go go")
    	a<-true
    	fmt.Println("xxx")
    }
    
    //信道案例
    
    package main
    /*
    输入 453  计算每一位的平方和和每一位的立方和的和
    squares = (4 * 4) + (5 * 5) + (3 * 3)
    cubes = (4 * 4 * 4) + (5 * 5 * 5) + (3 * 3 * 3)
    output = squares + cubes
     */
    
    
    import (
    	"fmt"
    )
    
    func calcSquares(number int, squareop chan int) {
    	sum := 0
    	for number != 0 {
    		digit := number % 10   //% 取余数 453对10取余数--》3--》5--》4
    		sum += digit * digit
    		number /= 10          // /除以  453除以10----》45--》5--》0
    	}
    	squareop <- sum
    }
    
    func calcCubes(number int, cubeop chan int) {
    	sum := 0
    	for number != 0 {
    		digit := number % 10
    		sum += digit * digit * digit
    		number /= 10
    	}
    	cubeop <- sum
    }
    
    func main() {
    	number := 4535
    	sqrch := make(chan int)
    	cubech := make(chan int)
    	go calcSquares(number, sqrch)
    	go calcCubes(number, cubech)
    	squares, cubes := <-sqrch, <-cubech
    	//squares:= <-sqrch
    	//cubes := <-cubech
    	fmt.Println("Final output", squares + cubes)
    }
    
    package main
    
    func main() {
    	//1 死锁
    
    	//var a chan int=make(chan int)
    	//a<-1  //一直阻塞在这,报死锁错误
    	//<-a     //一直阻塞在这,报死锁错误
    
    	//2 单向信道(只写或者只读)
    	//sendch := make(chan int) //定义一个可写可读信道
    	//go sendData(sendch)
    	//fmt.Println(<-sendch)  //只能往里写值,取值报错
    
    	//3 信道的关闭 close
    	//sendch := make(chan int)
    	//close(sendch)
    
    }
    func sendData(sendch chan<- int) {  //转成只写信道
    	sendch <- 10
    	//<-sendch  //只要读就报错
    }
    
    
    package main
    
    import (
    	"fmt"
    )
    
    func producer(chnl chan int) {
    	for i := 0; i < 10; i++ {
    		chnl <- i
    	}
    	close(chnl)
    }
    func main() {
    	ch := make(chan int)
    	go producer(ch)
    	for v := range ch {  //如果信道没关闭,一直取值,直到没有值,会报死锁
    		fmt.Println("Received ",v)
    	}
    }
    
    

    5 缓冲信道

    //有缓冲信道(信道可以放多个值)
    
    package main
    
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    
    func main() {
    	//1 有缓冲信道的定义和死锁问题
    	//var a chan int =make(chan int,4)  //长度为4的有缓冲信道
    	//a<-1
    	//a<-2
    	////a<-3
    	////a<-4
    	////管子满了
    	////a<-5  //报死锁错误
    	////推断出无缓冲信道 var a chan int =make(chan int,0)
    	//fmt.Println(<-a)
    	//fmt.Println(<-a)
    	////管子没有东西了,再取,报死锁
    	//fmt.Println(<-a)
    
    	//2 信道的容量和长度
    	//长度是目前管道中有几个值,容量是管道最多能容纳多少值
    	//var a chan int =make(chan int,4)
    	//fmt.Println(len(a))
    	//fmt.Println(cap(a))
    	//a<-1
    	//a<-2
    	//fmt.Println(len(a))
    	//fmt.Println(cap(a))
    
    	//3 小案例(通过信道实现goroutine的同步)
    	//var a chan int =make(chan int,3)
    	////b:=<-a
    	//go test3(a)
    	//
    	//fmt.Println(<-a)
    	//
    	//fmt.Println(<-a)
    
    	//4 通过waitgroup实现同步
    		no := 3
    		var wg sync.WaitGroup  //值类型,没有初始化,有默认值
    		for i := 0; i < no; i++ {
    			wg.Add(1)
    			go process(i, &wg)
    		}
    		wg.Wait() //add了几次,必须有几个wg.Done()对应,否则一直等在这
    		fmt.Println("All go routines finished executing")
    }
    
    func process(i int, wg *sync.WaitGroup) {
    	fmt.Println("started Goroutine ", i)
    	time.Sleep(2 * time.Second)
    	fmt.Printf("Goroutine %d ended
    ", i)
    	wg.Done()
    }
    
    
    
    //func test3(a chan int)  {
    //	a<-1
    //
    //	time.Sleep(time.Second*2)
    //	fmt.Println("假设我在运算")
    //
    //	a<-2
    //	close(a)
    //
    //}
    
    
    

    6 异常处理

    //异常处理
    package main
    
    import "fmt"
    
    //func main() {
    //	f1()
    //	f2()
    //	f3()
    //}
    //func f1()  {
    //	fmt.Println("f1")
    //}
    //
    //func f2()  {
    //	fmt.Println("f2")
    //	//如果这个地方出了异常
    //}
    //func f3()  {
    //	fmt.Println("f3")
    //}
    
    //defer:延迟执行,即便程序出现严重错误,也会执行
    //panic:主动抛出异常 raise
    //recover:恢复程序,继续执行
    
    //func main() {
    //	//defer fmt.Println("我最后才执行")  //先注册,等函数执行完成后,逆序执行defer注册的代码
    //	//defer fmt.Println("ddddd")
    //	defer func() {
    //		fmt.Println("我最后才执行")
    //	}()
    //	defer func() {
    //		fmt.Println("我最后才执行")
    //		//出异常
    //		//这个代码执行不到了
    //	}()
    //
    //	fmt.Println("111")
    //	fmt.Println("222")
    //	panic("我出错了")  //主动抛出异常
    //	//var a []int =make([]int,2,3)
    //	//fmt.Println(a[9])
    //	fmt.Println("这句话还会执行吗 ?不会了")
    //}
    
    //在defer中恢复程序,继续执行
    func main() {
    
    	f1()
    	f2()
    	f3()
    }
    func f1()  {
    	fmt.Println("f1")
    }
    
    func f2()  {
    	defer func() {
    		//recover() //恢复程序继续执行
    		if err:=recover();err!=nil{  //err 如果不为nil(空),表示出了异常
    			fmt.Println(err)  //把异常信息打印出来
    		}
    
    	}()
    	fmt.Println("f2")
    	//如果这个地方出了异常
    	panic("我出错了")
    
    	fmt.Println("永远执行不到")
    }
    func f3()  {
    	fmt.Println("f3")
    }
    
    // python中
    //print('ssss')
    //try:
    //	print('ssss')
    //	raise("xxxx")
    //	print('我永远不会执行')
    //except Exception as e:
    //	print(e)
    //finally:
    //	print('我永远会执行')
    
    //go 中
    //print('ssss')
    //defer func() {
    //	if err:=recover();err!=nil{
    //		fmt.Println(err)
    //	}
    //	//finally 写在这
    //	print('我永远会执行')
    //}()
    //print('ssss')
    //panic("xxxx")
    //print('我永远不会执行')
    

    补充

    1 进程,线程,协程

    # python中为什么让你开进程,由于cpython解释器,有GIL锁,同一时刻,只能有一个线程执行
    # 开进程--》相当于开了多个线程,重新起了一个cpython解释器,运行代码
    
  • 相关阅读:
    Navicat 回复 psc 文件 Mysql
    android SDK 更新问题完美解决 http://dl-ssl.google.com refused
    利用android来赚钱
    苹果应用 Windows 申请 普通证书 和Push 证书 Hbuilder 个推(2)
    苹果应用 Windows 申请 普通证书 和Push 证书 Hbuilder 个推
    Java version 32转64位
    浅谈Jquery中的bind()、live()、delegate()、on()绑定事件方式
    JavaScript之深浅拷贝
    关于一道JS面试题的思考
    EasyUI-Tooltip(提示框)学习
  • 原文地址:https://www.cnblogs.com/yafeng666/p/12849313.html
Copyright © 2020-2023  润新知