Golang|Channel 相关用法理解

文章目录

    • [用 channel 作为并发小容器](#用 channel 作为并发小容器)
    • [channel 的遍历](#channel 的遍历)
    • [channel 导致的死锁问题](#channel 导致的死锁问题)
    • [用 channel 传递信号](#用 channel 传递信号)
    • [用 channel 并行处理文件](#用 channel 并行处理文件)
    • [用channel 限制接口的并发请求量](#用channel 限制接口的并发请求量)
    • [用 channel 限制协程的总数量](#用 channel 限制协程的总数量)

用 channel 作为并发小容器


  • 注意这里的 ok 如果为 false,表示此时不仅channel为空,而且channel已经被关闭了

channel 的遍历

  • 注意,遍历会使头指针往后移,相当于取走元素
  • 如果 close channel 注释掉,也不会报错,但是会阻塞,导致输出bye bye这一句代码得不到执行
  • 遍历的另外一种写法

channel 导致的死锁问题

  • 上面的main方法是等3秒钟结束main协程,更好的方法是使用waitGroup


  • 如果 close channel 注释掉,程序执行的时候会报错 fatal error: all goroutines are asleep - deadlock!
  • travese和main都阻塞了

用 channel 传递信号

  • 可以用向channel中传递信号,代替waitGroup,优雅地等子协程结束
  • struct{} 空结构体类型,空结构体实例 struct{}{}
  • 空结构体在go语言里是一种特殊的结构体,go语言通过一个统一的引用变量来表示所有的空结构体,而且不占用任何的内存空间
  • 使用空结构体,语义会更加明确且不占内存
  • 在 Go 语言(Golang)中,reflect 是一个非常强大的包,提供了 运行时反射机制,可以在运行时检查变量的类型、获取或设置变量的值。
go 复制代码
// 获取类型和值

var x int = 42
t := reflect.TypeOf(x) // reflect.Type
v := reflect.ValueOf(x) // reflect.Value

fmt.Println("类型:", t)      // int
fmt.Println("值:", v.Int()) // 42
go 复制代码
// 修改变量的值(需要传指针)

var x int = 10
v := reflect.ValueOf(&x)           // 注意要传指针
v.Elem().SetInt(100)               // 修改值
fmt.Println("x的新值:", x)         // 100
go 复制代码
// 检查变量类型

func checkType(i interface{}) {
    t := reflect.TypeOf(i)
    switch t.Kind() {
    case reflect.Int:
        fmt.Println("是整数")
    case reflect.String:
        fmt.Println("是字符串")
    default:
        fmt.Println("其他类型")
    }
}
go 复制代码
// 结构体字段操作

type Person struct {
    Name string
    Age  int
}

p := Person{"Tom", 30}
v := reflect.ValueOf(p)
t := reflect.TypeOf(p)

for i := 0; i < t.NumField(); i++ {
    field := t.Field(i)
    value := v.Field(i)
    fmt.Printf("%s: %v\n", field.Name, value)
}

用 channel 并行处理文件

  • channel 不仅可以当作数据容器使用,也可以当作信号容器来使用
  • 下面这个例子是要把多个txt文件合并为一个txt文件,一个常规的思路就是我们顺序读取文件,每读取一行就把这一行对应地写入到新的文件里面去,但是io操作很消耗时间,且三个文件毫不相关,怎么加速?
  • 考虑三个goroutine并行读,且往一个buffer channel写数据,由一个goroutinue往buffer channel里读数据写入文件,这样可以协调读者和写者的速度不匹配问题
  • 初始化pc_sync里面有3个元素,协程完成后会从pc_sync取走一个元素,当所有协程结束后,pc_sync为空


用channel 限制接口的并发请求量

  • 有时候我们需要限制微服务接口的并发请求度,因为有些接口会涉及到大量的cpu计算或者是内存开销,如果瞬间并发度太大的话,服务器负载会很高
  • 但是如果限制了的话必然会牺牲用户的体验
  • 用channel的阻塞机制实现

用 channel 限制协程的总数量

  • 需要封装,对于所有的协程创建都去走一个统一的入口
  • ticker 实际上就是每隔一段时间会给ticker.C中放入一个元素



相关推荐
阿俊-全栈开发1 小时前
LikeShop 单商户SaaS商城分销模块二开:佣金计算与结算逻辑实现
java·开发语言·微服务·likeshop·likeshop开源商城·likeshop多商户
m0_380743874 小时前
C++中的freopen的用法实例详解
开发语言·c++
Escalating_xu5 小时前
【Python】基础语法(1):常量、变量、类型、输入输出与运算符
开发语言·python
jimy15 小时前
polymorph.cpp里面的“析构函数、智能指针”问题
开发语言·c++
m0_380743875 小时前
PHP 8.3 缓存清除不生效怎么排查
开发语言·php
朝朝辞暮i5 小时前
C++ 第 6 课:switch —— 多状态选择
开发语言·c++·算法
小凡geo6 小时前
本地商家 GEO:用脚本一键生成 FAQPage 结构化数据,让 AI 切片更稳
开发语言·人工智能·python·microsoft·搜索引擎·ai
朝朝辞暮i6 小时前
C++ 第 4 课:if / else —— 让程序自己做决定
开发语言·c++
波力海苔夹心脆6756 小时前
C# 值类型与引用类型详解:存储位置、赋值机制、参数传递、相等比较、装箱拆箱与常见陷阱
开发语言·jvm·经验分享·笔记·c#·.net
蜗牛互联网6 小时前
WSL Containers GA:本地AI容器的生命周期、网络与治理验收
java·网络·人工智能·后端