当前位置: 首页> 房产> 市场 > 青岛优化网站技术_婚庆公司排名前十_网站免费优化_seo自学教程推荐

青岛优化网站技术_婚庆公司排名前十_网站免费优化_seo自学教程推荐

时间:2025/7/9 14:27:47来源:https://blog.csdn.net/hmx224_2014/article/details/145099793 浏览次数:1次
青岛优化网站技术_婚庆公司排名前十_网站免费优化_seo自学教程推荐

在这里插入图片描述

Go语言的并发是通过协程(goroutine)实现的。Go协程是轻量级的线程,允许多个任务同时执行,且Go运行时会高效地管理它们。在Go中使用并发协程的方式非常简便,也很强大。以下是一些关于Go协程的基础用法和并发控制方法:

文章目录

      • 1. 启动协程
      • 2. 使用 `sync.WaitGroup` 管理协程
      • 3. 使用通道(Channel)进行协程间通信
        • 创建并使用通道
        • 带缓冲的通道
      • 4. 使用 `select` 多路复用通道
      • 5. 使用 `sync.Mutex` 实现互斥锁
      • 6. 使用 `sync.Once` 确保只执行一次
        • 小结
      • 7.用 `context` 管理并发任务
        • 实际业务场景

1. 启动协程

要启动一个协程,只需要在函数调用前加上关键字 go

package mainimport ("fmt""time"
)func printMessage(message string) {fmt.Println(message)
}func main() {go printMessage("Hello from goroutine!")fmt.Println("Hello from main!")time.Sleep(time.Second) // 给协程时间执行完毕
}

在这个例子中,printMessage 函数会作为一个协程执行,因此main函数中的打印语句和协程可能会并行执行。

注意main函数运行完毕时,程序会立即退出,即使其他协程仍在执行。所以在这里用time.Sleep让主协程等待,确保子协程有时间完成工作。

2. 使用 sync.WaitGroup 管理协程

sync.WaitGroup 是Go提供的一个结构,可以用来等待一组协程完成。

package mainimport ("fmt""sync"
)func printNumber(num int, wg *sync.WaitGroup) {defer wg.Done() // 调用Done来减少计数fmt.Println(num)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 5; i++ {wg.Add(1) // 增加计数go printNumber(i, &wg)}wg.Wait() // 等待所有协程完成fmt.Println("All goroutines finished!")
}

3. 使用通道(Channel)进行协程间通信

通道是Go内置的并发控制机制,协程间可以通过通道进行数据传递,避免数据竞争。

channelnil非空空的满的没满
接收阻塞接收值阻塞接收值接收值
发送阻塞发送值发送值阻塞发送值
关闭panic关闭成功,读完数据后返回零值关闭成功,返回零值关闭成功,读完数据后返回零值关闭成功,读完数据后,返回零值

关闭后的通道有以下特点:

  • 对一个关闭的通道再发送值就会导致panic。
  • 对一个关闭的通道进行接收会一直获取值直到通道为空。
  • 对一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值。
  • 关闭一个已经关闭的通道会导致panic。
创建并使用通道
package mainimport ("fmt"
)func sum(a, b int, resultChan chan int) {result := a + bresultChan <- result // 将结果发送到通道
}func main() {resultChan := make(chan int) // 创建一个int类型的通道go sum(3, 5, resultChan) // 启动协程计算result := <-resultChan   // 从通道中接收结果fmt.Println("Sum:", result)
}
带缓冲的通道

Go支持缓冲通道,允许发送者发送多于一个数据而不需要立刻被接收。

package mainimport ("fmt"
)func main() {bufferedChan := make(chan int, 3) // 缓冲大小为3bufferedChan <- 1bufferedChan <- 2bufferedChan <- 3fmt.Println(<-bufferedChan)fmt.Println(<-bufferedChan)fmt.Println(<-bufferedChan)
}

4. 使用 select 多路复用通道

select 语句可以同时等待多个通道操作,执行第一个准备好的操作。

package mainimport ("fmt""time"
)func main() {chan1 := make(chan string)chan2 := make(chan string)go func() {time.Sleep(2 * time.Second)chan1 <- "Message from channel 1"}()go func() {time.Sleep(1 * time.Second)chan2 <- "Message from channel 2"}()select {case msg1 := <-chan1:fmt.Println(msg1)case msg2 := <-chan2:fmt.Println(msg2)case <-time.After(3 * time.Second):fmt.Println("Timeout")}
}

5. 使用 sync.Mutex 实现互斥锁

当多个协程需要访问共享资源时,可以使用sync.Mutex来保证同一时间只有一个协程可以访问。

package mainimport ("fmt""sync"
)var counter int
var mutex sync.Mutexfunc increment(wg *sync.WaitGroup) {defer wg.Done()mutex.Lock()   // 加锁counter++mutex.Unlock() // 解锁
}func main() {var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go increment(&wg)}wg.Wait()fmt.Println("Final counter:", counter)
}

6. 使用 sync.Once 确保只执行一次

有些场景下,需要确保某段代码只执行一次(例如初始化配置),可以使用sync.Once

package mainimport ("fmt""sync"
)var once sync.Oncefunc initialize() {fmt.Println("Initialized!")
}func main() {for i := 0; i < 3; i++ {once.Do(initialize) // 只会执行一次}
}
小结
  • 启动协程:使用go关键字。
  • 等待协程完成:使用sync.WaitGroup
  • 协程间通信:使用通道(Channel)。
  • 通道多路复用:使用select
  • 互斥控制:使用sync.Mutex
  • 单次执行:使用sync.Once

Go的并发特性为编写高效的并发程序提供了强大支持,同时也有丰富的同步原语来避免竞态条件。

7.用 context 管理并发任务

使用 context.Context 可以优雅地管理并发任务,尤其是在需要统一控制超时、取消操作或共享上下文数据时。

实际业务场景
  1. 超时管理
    • API 请求或任务需要在一定时间内完成,否则强制取消,避免资源浪费。
  2. 任务协调
    • 多个并发任务共享相同的上下文状态,例如取消操作。
  3. 优雅退出
    • 确保并发任务能够响应外部取消信号,安全退出而非强制终止。
package mainimport ("context""fmt""math/rand""sync""time"
)// 模拟一个工作函数
func worker(ctx context.Context, id int, wg *sync.WaitGroup) {defer wg.Done()for {select {case <-ctx.Done():// 任务被取消时结束fmt.Printf("Worker %d stopped: %v\n", id, ctx.Err())returndefault:// 模拟工作time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)fmt.Printf("Worker %d is processing\n", id)}}
}func main() {// 设置超时时间的上下文ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)defer cancel()// 创建 WaitGroup 来等待所有任务完成var wg sync.WaitGroup// 启动多个并发任务numWorkers := 5for i := 1; i <= numWorkers; i++ {wg.Add(1)go worker(ctx, i, &wg)}// 等待所有任务结束wg.Wait()fmt.Println("All workers stopped.")
}
关键字:青岛优化网站技术_婚庆公司排名前十_网站免费优化_seo自学教程推荐

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: