首页 > 其他分享 >go:接口、并发与协程、信道、缓冲信道、mutex、异常处理

go:接口、并发与协程、信道、缓冲信道、mutex、异常处理

时间:2023-06-27 09:56:09浏览次数:46  
标签:协程 fmt go 信道 mutex func Println main

目录

接口

1.实现多个接口
2.接口嵌套
3.接口零值
package main

import "fmt"

// 接口

//1   实现多个接口   具体类型可以赋值给多种接口类型
//type Animal interface {
//	run()
//}
//
//type Dog interface {
//	eat()
//}
//
//type MuYangDog struct {
//	name string
//	age  int
//}
//
//func (d *MuYangDog) eat() {
//	fmt.Println(d.name, "在吃东西")
//}
//func (d *MuYangDog) run() {
//	fmt.Println(d.name, "在跑")
//}
//func main() {
//	//var d Dog = &MuYangDog{name: "牧羊犬", age: 6}
//	//d.eat()
//
//	var a Animal = &MuYangDog{name: "牧羊犬", age: 6}
//	a.run()
//}

// 2 接口嵌套
//type Animal interface {
//	run()
//}
//
//type Dog interface {
//	eat()
//	Animal // 就等同于把Animal中的所有方法放在这里了
//}
//type MuYangDog struct {
//	name string
//	age  int
//}
//
//func (d *MuYangDog) eat() {
//	fmt.Println(d.name, "在吃东西")
//
//}
//
//func (d *MuYangDog) run() {
//	fmt.Println(d.name, "在跑")
//
//}
//func main() {
//
//	var d Animal = &MuYangDog{name: "牧羊犬"}
//	d.run()
//}

// 2 接口零值---->引用类型

type Dog interface {
	eat()
}
type MuYangDog struct {
	name string
	age  int
}

func (d *MuYangDog) eat() {
	fmt.Println(d.name, "在吃东西")

}

func main() {

	var d Dog
	fmt.Println(d) // nil
}

并发与协程

# 并发:一段时间内,执行多个任务的能力
# 并行:同一时刻,执行多个任务的能力  (必须有多核支持)

# 实现并发
     1 开启多进程(耗费资源)
     2 开启多线程
     3 开启协程
    
# 正常语言,就是开启多线程,实现并发,python由于GIL锁的存在,同一时刻只能有一个线程在执行
     python中计算密集型(耗费cpu)----》开多进程
     pyhton中IO密集型-----》开启多线程
    
    
     其他语言,只要开启了多线程,就能利用多核优势
    
     go语言,进程,线程都不需要,开启协程
         我们认为:开启多个协程,因为在一个线程下,也不能利用多核优势
         所以go内置了,go的协程不是普通协程,它是 线程池+协程
        
        
    GMP模型
         G:go中开启一个协程叫 goroutine   
         P:Processer 处理器(相当于程序层面的线程)
         M:thread  操作系统线程

image

package main

import (
	"fmt"
	"time"
)

// 协程

func task(i int) {
	fmt.Println("我是任务,我开始干活了", i)
	time.Sleep(2 * time.Second)
	fmt.Println("我是任务,干完活了", i)

}

func main() {
	fmt.Println("我是主协程")
	//// 执行任务,同步执行
	//task()

	// 执行任务,异步执行  ,开启了一个go协程
	//go task()
	//go task()
	//go task()
	//go task()

	for i := 0; i < 10; i++ {
		go task(i)

	}
	time.Sleep(3 * time.Second)
	fmt.Println("我是主协程,任务执行完了")

}

信道、缓冲信道

# 多个goroutine之间通信
	-可以通过共享变量--->mutex保证并发安全
    -信道,通道 channel
    
# 不要通过共享内存来通信,而应该通过通信来共享内存
package main

// 信道  一种类型,定义成变量,可以多个协程之间使用

//func main() {
//1 定义信道--->没有初始化,零值 是nil,说明引用类型,传递到函数中,不需要取地址
//var c chan int
//fmt.Println(c) // nil

// 2 定义并初始化
//var c chan int = make(chan int)
//fmt.Println(c) // 0xc00005c060  内存地址,引用

// 3 初始化后,放值,取值
// 放值
//c <- 1 // 把数字1 放入到信道c 中   //deadlock
//c <- 2
//c <- 3

// 取值
//var i int=<-c
//var i =<-c
//i := <-c //从信道中取出一个值
//fmt.Println(i)

// 4 信道默认,放值取值都是阻塞的,多个协程,一个协程放,另一个协程取值,才不会死锁
//	var c = make(chan int)
//	fmt.Println("主goroutine开始起来")
//	go sendEmail(c) // 把信道变量,传入协程函数中
//
//	//<-c // 等待从c中取值   取出来,不要了
//	i := <-c // 等待从c中取值
//	fmt.Println("主goroutine结束了", i)
//
//}
//
//func sendEmail(c chan int) {
//	fmt.Println("发邮件了")
//	time.Sleep(3 * time.Second)
//	fmt.Println("邮件发完了")
//	c <- 1 // 发完邮件了,放1进去
//
//}

// 5 单向信道 (只能放或只能取

//func main() {
//	var c = make(chan bool)
//	fmt.Println(<-c)
//}
//
//// func task3(c <-chan bool) {    // 只读信道
//func task3(c chan<- bool) { // 只写信道
//	time.Sleep(2 * time.Second)
//	//c <- true
//	//<-c
//
//}

// 6 关闭信道 ,关闭后,不能再放值,取值了   close 内置函数关闭
//
//func task4(c chan int) {
//	time.Sleep(2 * time.Second)
//	c <- 1
//	close(c) // 信道关闭
//}
//
//func main() {
//	var c = make(chan int)
//
//	go task4(c)
//	for {
//		v, ok := <-c
//		if ok {
//			fmt.Println("信道没关闭,取出来了")
//			fmt.Println(v)
//		} else {
//			fmt.Println("信道被关了,结束死循环")
//			break
//		}
//	}
//}

// 6.1 稍微复杂的信道关闭

//func task4(c chan int) {
//	for i := 0; i < 10; i++ {
//		c <- i
//	}
//
//	close(c) // 信道关闭
//}
//
//func main() {
//	var c = make(chan int)
//
//	go task4(c)
//	for {
//		v, ok := <-c
//		if ok {
//			fmt.Println("信道没关闭,取出来了")
//			fmt.Println(v)
//		} else {
//			fmt.Println("信道被关了,结束死循环")
//			break
//		}
//	}
//}

// 6.2 上面是for死循环,可以使用range循环
//func task4(c chan int) {
//	for i := 0; i < 10; i++ {
//		c <- i
//	}
//
//	close(c) // 信道关闭
//}
//
//func main() {
//	var c = make(chan int)
//
//	go task4(c)
//	for i := range c { //只要信道关闭了,循环就结束了
//		fmt.Println(i)
//	}
//}
package main

import (
	"fmt"
	"sync"
)

//WaitGroup:等待其他协程执行完成

// 1 通过信道实现,等待所有任务执行完成
//func task5(c chan int, i int) {
//	fmt.Println("第", i, "个协程执行")
//	c <- i
//}
//
//func main() {
//	var c = make(chan int, 5)
//	for i := 0; i < 5; i++ {
//		go task5(c, i)
//	}
//
//	// 等都执行完才结束
//	for i := 0; i < 5; i++ {
//		<-c
//	}
//	fmt.Println("主协程结束了")
//}

// 2 通过  等待所有协程执行完成
func task5(wg *sync.WaitGroup, i int) {
	fmt.Println("第", i, "个协程执行")
	wg.Done() // 这个任务完成,就写一个Done

}

func main() {
	var wg sync.WaitGroup // 值类型  没有初始化
	//fmt.Println(wg)
	wg.Add(5)
	for i := 0; i < 5; i++ {
		//wg.Add(1)        // 执行5次
		go task5(&wg, i) //一定要取地址
	}

	wg.Wait()
	fmt.Println("主协程结束了")
}

/*
WaitGroup:等待其他协程执行完成
用法:定义   值类型
wg.Add(1)   开启一个协程,就要加1

wg.Done()  一个协程结束,就Done一次,其实就是减一

wg.Wait()  等待计数器为0,继续往后执行
*/

mutex

# go 可以通过共享变量,实现通信
package main

import (
	"fmt"
	"sync"
)

var x = 0

func add(wg *sync.WaitGroup, lock *sync.Mutex) {
	// 临界区要加锁
	lock.Lock()
	x = x + 1
	lock.Unlock()
	wg.Done()
}
func main() {
	var w sync.WaitGroup
	var lock sync.Mutex // 值类型
	//fmt.Println(lock)
	for i := 0; i < 1000; i++ {
		w.Add(1)
		go add(&w, &lock)
	}
	w.Wait()
	fmt.Println("final value of x", x)
}

异常处理

package main

import "fmt"

// 异常处理  go 没有try语法,使用panic,defer,recover实现异常处理

func main() {

	// 1 panic   内置函数,主动抛出异常,   raise
	//fmt.Println("111")
	//panic("我错了")
	//fmt.Println(222)

	// 3 defer 先注册后调用,即便出了异常,也会执行
	// 2 recover 内置函数,回复程序,继续执行

	//defer func() {
	//	recover() // 恢复程序
	//}()
	//fmt.Println("111")
	//panic("我错了")
	//fmt.Println(222)
	//

	// 4 正常的go异常处理
	test()

}

func test() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("出错了", err)
		}

		// 这是finally执行的地址
		//fmt.Println("文论是否出错,我都会执行")
	}()

	fmt.Println("test执行了")
	//panic("报错了")
	//var s []int
	//fmt.Println(s[9])
	fmt.Println("test结束了")
}

// 其他语言
/*
try:
	写代码
except Except as e:
	出错了
finally:
	都会执行
*/

// go
/*
defer func() {
	if err := recover(); err != nil {
		出错了,err就是e,就是错误对象
	}
	都会执行
}()
写代码写代码写代码写代码写代码写代码

*/

标签:协程,fmt,go,信道,mutex,func,Println,main
From: https://www.cnblogs.com/wxlxl/p/17507878.html

相关文章

  • 【5.0】知识点小结(协程进阶)
    【5.0】知识点小结(协程进阶)【一】IO模型简介我们研究的IO都是基于网络IO的Stevens在文章中一共比较了五种IOModel:blockingIOnonblockingIOIOmultiplexingsignaldrivenIO---(忽略)asynchronousIO由signaldrivenIO(信号驱动IO)在实际中并不常用,所以主要介绍......
  • 多进程和多线程以及协程的创建模板
    【一】开启多进程的创建模板(基于Process模块)【1】方式一:创建多进程importmultiprocessingdefworker(n):"""子进程要执行的任务"""print(f'子进程{n}正在执行')defmain():task_lists=[]foriinrange(100)#创建一个进程对象......
  • m基于NOMA-CoMP系统的保密信道中断概率的matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:   2.算法涉及理论知识概要        随着数字通信技术的不断发展,无线通信作为一种高效且灵活的通信方式,已经成为了现代社会中不可或缺的一部分。然而,随着通信技术的不断进步,网络安全问题也逐渐成为了无线通信领域中的热点......
  • cpp condition_variable wait_for unique_mutex,chrono::seconds
    #include<chrono>#include<condition_variable>#include<ctime>#include<fstream>#include<future>#include<iomanip>#include<iostream>#include<thread>#include<uuid/uuid.h>#include<vector......
  • golang 常用控制协程的三种方式
    waitGroupwaitGroup这种方式适用于一个任务可以被拆分成几个子任务,并且子任务之间的关联程度不高,全部的子任务都完成,才会进行下一阶段的任务。packagemainimport( "fmt" "sync" "time")funcmain(){ varwgsync.WaitGroup wg.Add(3) gofunc(){ deferwg.Do......
  • Kotlin协程:Flow基础原理
    本文分析示例代码如下:launch(Dispatchers.Main){flow{emit(1)emit(2)}.collect{delay(1000)withContext(Dispatchers.IO){Log.d("liduo","$it")}Log.d("liduo",&......
  • 简单记录下 Spring Boot 使用虚拟线程Virtual Threads(Java的协程)的方法
    在之前的文章中,简单描述了将springboot2.x升级springboot3.1的版本的过程。本文将简单介绍如何在spring中引入虚拟线程,在文章最后会放上一些关于虚拟线程的官方参考资料。JDK22会引来重要特性,VirtualThreads也就是协程功能。与主流的async、await方案(C#、JS等语言)相比......
  • [纵横网络靶场社区]隐信道数据安全分析
    附件flag-woody.mp3是一首歌,mp3格式,听了一下,Audacity打开看了一下没发现什么异常;mp3隐写试了一下也没什么线索。回到题目名称和描述。信道隐写,某种private的方式将信息传递出去。使用010Editor打开,分析文件结构。可以发现在每个MPEG_FRAMEmf下的4字节MPEG_HEADERmpeg_hdr中的......
  • kotlin协程原理分析项目实战
    自从6.0加入动态权限之后,很多地方都要用到,开始的时候使用的原生代码写权限请求,代码格式如:if(应用是否已经请求了该权限组){权限请求后的代码}else{请求权限}然后不知道在fragment或是activity里面重写overrideonRequestPermissionsResult{if(请求成功){......
  • std::thread 二:互斥量(带超时的互斥量 timed_mutex())
     timed_mutex、 try_lock_for、 try_lock_until #include<iostream>#include<thread>#include<mutex>#include<list>usingnamespacestd;classA{public:voidinNum(){for(inti=0;i<10000;i++)......