Golang 并发编程

server/2024/9/23 9:25:29/

Golang 并发编程

Goroutine

什么是协程

创建 Goroutine

主 goroutine (main函数)退出后,其它的工作 goroutine 也会自动退出

package mainimport ("fmt""time"
)func myFunc() {i := 0for {i++fmt.Println("func: ", i)time.Sleep(1 * time.Second)}
}func main() {go myFunc()i := 0for {i++fmt.Println("main: ", i)time.Sleep(1 * time.Second)}
}
main:  1
func:  1
func:  2
main:  2

Goexit 函数

调用 runtime.Goexit() 将立即终止当前 goroutine 执⾏

func myFunc() {i := 0for {i++fmt.Println("func: ", i)time.Sleep(1 * time.Second)if i == 10 {fmt.Println("func OVER ~")runtime.Goexit()}}
}func main() {go myFunc()i := 0for {i++fmt.Println("main: ", i)time.Sleep(1 * time.Second)}
}
...
func:  9
main:  9
main:  10
func:  10
func OVER ~
main:  11
main:  12
...

匿名函数

func main() {func() {fmt.Println("hello, I don't have name.")}()
}
func main() {fun := func() {fmt.Println("hello, I don't have name.")}fun()
}

Channel

什么是 Channel

channel 用来解决go程的同步问题以及go程之间数据共享(数据传递)的问题。

⽤类型 channel可用于多个 goroutine 通讯。其内部实现了同步,确保并发安全。

创建管道

package mainimport ("fmt""time"
)var c chan intfunc f(name string) {for {i := <-cfmt.Println(name, ": ", i)i++c <- itime.Sleep(1 * time.Second)}
}func main() {c = make(chan int)go f("fun1")go f("fun2")c <- 0for {}
}
fun2 :  0
fun1 :  1
fun2 :  2
fun1 :  3
fun2 :  4
fun1 :  5
fun2 :  6

Channel 的缓冲

无缓冲:通道不保存数据,生产者会等待消费者,将数据放到管道中。

有缓存:类似消息队列,可以保存在管道中。

package mainimport ("fmt""time"
)var c chan intfunc f(name string) {for {i := <-cfmt.Println(name, ": ", i)i++c <- itime.Sleep(10 * time.Millisecond)}
}func main() {// 有缓冲的 Channelc = make(chan int, 1)go f("fun1")go f("fun2")c <- 0time.Sleep(1 * time.Second)
}

会产生同一个 go 程会执行多次的效果

image-20240809153821768
func main() {// 无缓冲的 Channelc = make(chan int)go f("fun1")go f("fun2")c <- 0time.Sleep(1 * time.Second)
}

两个 go 程交替运行,channel 作为锁,相互阻塞线程。

image-20240809153902951

关闭 channel

package mainimport ("fmt"
)func main() {c := make(chan int)go func() {for i := 0; i < 5; i++ {c <- i}close(c)}()for {// ok为true说明channel没有关闭,为false说明管道已经关闭if data, ok := <-c; ok {fmt.Println(data)} else {break}}fmt.Println("Finished")
}

range 函数

可以用 range 迭代操作 channel

package mainimport ("fmt"
)func main() {c := make(chan int)go func() {for i := 0; i < 5; i++ {c <- i}close(c)}()for data := range c {fmt.Println(data)}fmt.Println("Finished")
}

select 函数

用于多路监控 channel

package mainimport ("fmt"
)func fibonacci(c, quit chan int) {x, y := 1, 1for {select {case c <- x:x, y = y, x+ycase <-quit:fmt.Println("quit")return}}
}func main() {c := make(chan int)quit := make(chan int)go func() {for i := 0; i < 6; i++ {fmt.Println(<-c)}quit <- 0}()fibonacci(c, quit)
}

Go Modules

配置

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

创建项目

go mod init github.com/wmh1024/demo_module
go get xxxx

replace

修改模块的版本依赖关系

go mod edit -replace=zinx@v0.0.0-20200306023939-bc416543ae24=zinx@v0.0.0-20200221135252-8a8954e75100

http://www.ppmy.cn/server/100464.html

相关文章

几个常用脚本

系统初始化 #!/bin/bash # 定义颜色常量 RED\033[0;31m GREEN\033[0;32m NC\033[0m # No Color #功能菜单 menu() {clearecho "请选择要执行的操作:"echo "1. 检查网络"echo "2. 关闭防火墙和SELinux"echo "3. 替换YUM源"echo "…

C# TreeView

添加 TreeView 控件&#xff1a;定义节点&#xff1a;添加节点&#xff1a;设置节点属性&#xff1a;处理节点事件&#xff1a;自定义节点绘制&#xff1a;数据绑定&#xff1a;节点选择&#xff1a;节点展开和折叠&#xff1a;搜索和过滤&#xff1a;示例代码总结 C# 中的 Tre…

【hexo博客问题】

windows下使用gitbash即可使用 其他bash会产生权限问题 npm install失败 $ npm install npm error code ENOENT npm error syscall open npm error path F:\pf_project\blog_pf\package.json npm error errno -4058 npm error enoent Could not read package.json: Error: E…

滑动窗口最大值问题

目录 一题目&#xff1a; 二思路汇总&#xff1a; 三解答代码&#xff1a; 一题目&#xff1a; leetcode原题链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 二思路汇总&#xff1a; 思路&#xff1a;滑动窗口&#xff0c;在数组位置建立一个双端队列利用出入队…

HarmonyOS应用开发者基础认证(二)

1、下面是ArkTS中常量名、枚举值名推荐的代码风格是&#xff1f; 答案&#xff1a; 全大写&#xff0c;下划线分割 分析&#xff1a;常量名、枚举值名采用全部大写&#xff0c;单词间使用下划线隔开。 const MAX_USER_SIZE 10000; enum UserType {TEACHER 0,STUDENT 1 };2、…

深入探究:IP到TCP/IP堆栈的详尽旅程

在互联网的世界里&#xff0c;数据的每一次旅行都是一个复杂而精妙的过程&#xff0c;涉及到TCP/IP协议栈的每一层。让我们一起深入探讨&#xff0c;从IP层开始&#xff0c;直到数据被应用程序接收的全过程。 **一、网络层&#xff1a;IP的使命** IP&#xff08;Internet Prot…

代码规范 —— QMQ 开发规范

优质博文&#xff1a;IT-BLOG-CN 一、代码规范 【1】消费者必须以Consumer结尾&#xff0c;生产者必须以Producer结尾。 【2】选择合适的消费模式&#xff1a;根据业务判断消费模式是集群模式还是广播模式&#xff0c;具体为&#xff1a;MessageConsumerProvider.addListene…

LeetCode面试题Day9|LeetCode58 最后一个单词的长度、LeetCode151 反转字符串中的单词

题目1&#xff1a; 指路&#xff1a; . - 力扣&#xff08;LeetCode&#xff09;58 最后一个单词的长度 思路与分析&#xff1a; 求最后一个单词的长度&#xff0c;最普遍的思路应该是从后往前遍历&#xff0c;定义一个计数器&#xff0c;遇到第一个非空格的字母则使计数器…