package main import ( "fmt" _ "time" "sync" ) // 需求:现在要计算 1-200 的各个数的阶乘,并且把各个数的阶乘放入到map中。 // 最后显示出来。要求使用goroutine完成 // 思路 // 1. 编写一个函数,来计算各个数的阶乘,并放入到 map中. // 2. 我们启动的协程多个,统计的将结果放入到 map中 // 3. map 应该做出一个全局的. var ( myMap = make(map[int]int, 10) //声明一个全局的互斥锁 //lock 是一个全局的互斥锁, //sync 是包: synchornized 同步 //Mutex : 是互斥 lock sync.Mutex ) //使用协程+管道 ===>??? // test 函数就是计算 n!, 让将这个结果放入到 myMap func test(n int) { res := 1 for i := 1; i <= n; i++ { res *= i } //这里我们将 res 放入到myMap //加锁 lock.Lock() myMap[n] = res //concurrent map writes? //解锁 lock.Unlock() } func main() { // 我们这里开启多个协程完成这个任务[200个] for i := 1; i <= 20; i++ { go test(i) } //休眠10秒钟【第二个问题 】 //time.Sleep(time.Second * 5) //这里我们输出结果,变量这个结果 lock.Lock() for i, v := range myMap { fmt.Printf("map[%d]=%d\n", i, v) } lock.Unlock() }
package main import ( "fmt" ) func main() { //演示一下管道的使用 //1. 创建一个可以存放3个int类型的管道 var intChan chan int intChan = make(chan int, 3) //2. 看看intChan是什么 fmt.Printf("intChan 的值=%v intChan本身的地址=%p\n", intChan, &intChan) //3. 向管道写入数据 intChan<- 10 num := 211 intChan<- num intChan<- 50 // //如果从channel取出数据后,可以继续放入 <-intChan intChan<- 98//注意点, 当我们给管写入数据时,不能超过其容量 //4. 看看管道的长度和cap(容量) fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 3, 3 //5. 从管道中读取数据 var num2 int num2 = <-intChan fmt.Println("num2=", num2) fmt.Printf("channel len= %v cap=%v \n", len(intChan), cap(intChan)) // 2, 3 //6. 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告 deadlock num3 := <-intChan num4 := <-intChan //num5 := <-intChan fmt.Println("num3=", num3, "num4=", num4/*, "num5=", num5*/) }
1 2 3 4 5 | intChan 的值=0xc000086080 intChan本身的地址=0xc000080018 channel len= 3 cap=3 num2= 211 channel len= 2 cap=3 num3= 50 num4= 98 |
package main import "fmt" func main() { var mapchan chan map[string]string mapchan = make(chan map[string]string,10) m1 := make(map[string]string,10) m1["name"] = "阿凡达" m1["age"] = "25" m2 := make(map[string]string,10) m2["name"] = "欧阳" m2["age"] = "28" mapchan <- m1 mapchan <- m2 fmt.Println(mapchan) }
package main import "fmt" func main() { intchan := make(chan int ,3) intchan <- 100 intchan <- 200 close(intchan) fmt.Println("11111111111") n1 := <-intchan fmt.Println(n1) //100 fmt.Println(<-intchan) //200 fmt.Println(<-intchan) //0 fmt.Println(<-intchan) //0 intchan <- 300 //panic: send on closed channel }

package main import ( "fmt" "time" ) //write Data func writeData(intChan chan int) { for i := 1; i <= 50; i++ { //放入数据 intChan<- i // fmt.Println("writeData ", i) //time.Sleep(time.Second) } close(intChan) //关闭 } //read data func readData(intChan chan int, exitChan chan bool) { for { v, ok := <-intChan if !ok { break } time.Sleep(time.Second) fmt.Printf("readData 读到数据=%v\n", v) } //readData 读取完数据后,即任务完成 exitChan<- true close(exitChan) } func main() { //创建两个管道 intChan := make(chan int, 10) exitChan := make(chan bool, 1) go writeData(intChan) go readData(intChan, exitChan) //time.Sleep(time.Second * 10) for { _, ok := <-exitChan if !ok { break } } }

package main import ( "fmt" "time" ) //向 intChan放入 1-8000个数 func putNum(intChan chan int) { for i := 1; i <= 80000; i++ { intChan<- i } //关闭intChan close(intChan) } // 从 intChan取出数据,并判断是否为素数,如果是,就 // //放入到primeChan func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) { //使用for 循环 // var num int var flag bool // for { //time.Sleep(time.Millisecond * 10) num, ok := <-intChan //intChan 取不到.. if !ok { break } flag = true //假设是素数 //判断num是不是素数 for i := 2; i < num; i++ { if num % i == 0 {//说明该num不是素数 flag = false break } } if flag { //将这个数就放入到primeChan primeChan<- num } } fmt.Println("有一个primeNum 协程因为取不到数据,退出") //这里我们还不能关闭 primeChan //向 exitChan 写入true exitChan<- true } func main() { intChan := make(chan int , 1000) primeChan := make(chan int, 20000)//放入结果 //标识退出的管道 exitChan := make(chan bool, 8) // 4个 start := time.Now().Unix() //开启一个协程,向 intChan放入 1-8000个数 go putNum(intChan) //开启4个协程,从 intChan取出数据,并判断是否为素数,如果是,就 //放入到primeChan for i := 0; i < 8; i++ { go primeNum(intChan, primeChan, exitChan) } //这里我们主线程,进行处理 //直接 go func(){ for i := 0; i < 8; i++ { <-exitChan } end := time.Now().Unix() fmt.Println("使用协程耗时=", end - start) //当我们从exitChan 取出了4个结果,就可以放心的关闭 prprimeChan close(primeChan) }() //遍历我们的 primeChan ,把结果取出 for { _, ok := <-primeChan if !ok{ break } //将结果输出 //fmt.Printf("素数=%d\n", res) } fmt.Println("main线程退出") }

package main import "fmt" func send(ch chan<- int,exitchan chan struct{}){ for i :=0 ; i<10 ;i++{ ch<- i } close(ch) var a struct{} exitchan<- a } func recv(ch <-chan int,exitchan chan struct{}){ for{ v,ok:= <-ch if !ok{ break } fmt.Println(v) } var a struct{} exitchan<- a } func main() { var ch chan int ch = make(chan int,10) exitchan := make(chan struct{},2) go send(ch,exitchan) go recv(ch,exitchan) //var total = 0 //for _ = range exitchan{ // total++ // if total ==2{ // break // } //} var total = 0 for{ _,ok:= <-exitchan if !ok{ break } total++ if total ==2{ break } } fmt.Println("结束") }

package main import "fmt" func main() { intchan := make(chan int,10) for i := 0;i<10;i++{ intchan <- i } stringchan := make(chan string ,5) for i:=0;i<5;i++{ stringchan<- "hello"+fmt.Sprintf("%d",i) } for{ select{ case v:= <-intchan: fmt.Printf("从intchan读取的数据%d\n",v) case v := <-stringchan: fmt.Printf("从stringchan读取的数据%d\n",v) default: fmt.Printf("都取不到了,不玩了") return } } }
package main import ( "time" "fmt" ) func sayHello(){ for i:=0;i<10;i++{ //time.Sleep(time.Second) fmt.Println("hello world") } } func test(){ defer func(){ if err := recover();err!=nil{ fmt.Println("test() 发生错误",err) } }() var myMap map[int]string //myMap = make(map[int]string,6) myMap[0] = "golang" } func main() { go sayHello() go test() time.Sleep(time.Second*10) }
GOROOT=D:\go #gosetup GOPATH=null #gosetup D:\go\bin\go.exe build -i -o C:\Users\Administrator\AppData\Local\Temp\___go_build_03_go.exe D:/gospace/03.go #gosetup D:\soft\GoLand\bin\runnerw.exe C:\Users\Administrator\AppData\Local\Temp\___go_build_03_go.exe #gosetup hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world test() 发生错误 assignment to entry in nil map
sync:
sync案例
上图每次执行结果都不相同
通过加互斥锁
本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/11203892.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能