Golang学习笔记--Channel

如何定义使用

定义

每个通道都有与之关联的类型。此类型是允许通道传输的数据类型。不允许使用该通道传输其他类型的数据。

通道的零值为nil。零通道没有任何用处,因此必须使用类似于 map 和 slice 的make来定义。

package main

import "fmt"

func main() {  
    var a chan int      // 定义 channel
    if a == nil {
        fmt.Println("channel a is nil, going to define it")
        a = make(chan int)
        fmt.Printf("Type of a is %T", a)   // 输出Type of a is chan int  
    }
}

使用(接收和发送消息)

data := <- a // read from channel a  
a <- data // write to channel a  

默认情况下,发送和接收到通道处于阻塞状态。当数据发送到通道时,主goroutine将在send语句中被阻塞,直到其他Goroutine从该通道读取数据为止。同样,当从通道读取数据时,将阻止读取,直到某些Goroutine将数据写入该通道为止。

此属性可帮助Goroutines有效通信,而无需使用其他编程语言中很常见的显式锁或条件变量。

一个简单的程序:程序实现 (1 * 1) (2 * 2) (3 * 3) ... (n * n) (1 * 1 * 1) (2 * 2 * 2) (3 * 3 * 3) ...(n * n * n)可以拆成两部分并发执行,一个 goroutine 计算平方和,一个计算立方和

package main

import (  
    "fmt"
)

func calcSquares(number int, squareop chan int) {  
    sum := 0
    for number != 0 {
        digit := number % 10
        sum  = digit * digit
        number /= 10
    }
    squareop <- sum
}

func calcCubes(number int, cubeop chan int) {  
    sum := 0 
    for number != 0 {
        digit := number % 10
        sum  = digit * digit * digit
        number /= 10
    }
    cubeop <- sum
} 

func main() {  
    number := 10
    sqrch := make(chan int)
    cubech := make(chan int)
    go calcSquares(number, sqrch)
    go calcCubes(number, cubech)
    squares, cubes := <-sqrch, <-cubech  // 利用 channel 使主 goroutine 等待结果    
    fmt.Println("Final output", squares   cubes)
}

死锁

有一个地方需要注意,在使用 channel 时可能会引发死锁,看下面一个例子

func main() {  
    ch := make(chan int)
    ch <- 5             
}

这段程序向 channel 发送数字5,但是没有接收方,所以会一直阻塞

单向通道

上述简单的例子展示了双向 channel 如何使用,但是也可以创建单向通道,即仅发送或接收数据的通道。

// 定义只发送channel
sendch := make(chan<- int)

但是这样做又有什么意义呢,无法从 channel 中读取数据。这是使用 channel 转换。可以将双向通道转换为仅发送或仅接收通道,反之亦然。

// 这里将 channel 转换为单项只发送
func sendData(sendch chan<- int) {  
    sendch <- 10
}

func main() {  
    // 定义一个双向 channel
    chnl := make(chan int)
    go sendData(chnl)
    fmt.Println(<-chnl)
}

关闭通道

发送者可以关闭该通道,以通知接收者该通道将不再发送任何数据。接收器可以在从通道接收数据时使用附加变量,以检查通道是否已关闭。

v, ok := <- ch  

在上面的语句中,如果该值是通过对通道的成功发送操作接收到的,则ok为真。如果ok为假,则表示我们正在从封闭的通道读取数据。从关闭的通道读取的值将是通道类型的零值。例如,如果通道是int通道,则从封闭通道接收的值将为0。

channel 和 for range 可以搭配使用

func producer(chnl chan int) {  
    for i := 0; i < 10; i   {
        chnl <- i
    }
    close(chnl)
}
func main() {  
    ch := make(chan int)
    go producer(ch)
    for v := range ch {       // 若channel 未关闭,则一直取数据
        fmt.Println("Received ",v)
    }
}

如果喜欢,请关注我的公众号,或者查看我的博客 http://packyzbq.coding.me. 我会不定时的发送我自己的学习记录,大家互相学习交流哈~weixin

GoLang学习笔记主要包括以下几个方面: 1. 语法规则:Go语言要求按照语法规则编写代码,例如变量声明、函数定义、控制结构等。如果程序中违反了语法规则,编译器会报错。 2. 注释:Go语言中的注释有两种形式,分别是行注释和块注释。行注释使用`//`开头,块注释使用`/*`开头,`*/`结尾。注释可以提高代码的可读性。 3. 规范代码的使用:包括正确的缩进和空白、注释风格、运算符两边加空格等。同时,Go语言的代码风格推荐使用行注释进行注释整个方法和语句。 4. 常用数据结构:如数组、切片、字符串、映射(map)等。可以使用for range遍历这些数据结构。 5. 循环结构:Go语言支持常见的循环结构,如for循环、while循环等。 6. 函数:Go语言中的函数使用`func`关键字定义,可以有参数和返回值。函数可以提高代码的重用性。 7. 指针:Go语言中的指针是一种特殊的变量,它存储的是另一个变量的内存地址。指针可以实现动态内存分配和引用类型。 8. 并发编程:Go语言提供了goroutine和channel两个并发编程的基本单位,可以方便地实现多线程和高并发程序。 9. 标准库:Go语言提供了丰富的标准库,涵盖了网络编程、文件操作、加密解密等多个领域,可以帮助开发者快速实现各种功能。 10. 错误处理:Go语言中的错误处理使用`defer`和`panic`两个关键字实现,可以有效地处理程序运行过程中出现的错误。 通过以上内容的学习,可以掌握Go语言的基本语法和编程思想,为进一步学习和应用Go语言打下坚实的基础。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Golang学习笔记](https://blog.csdn.net/weixin_52310067/article/details/129467041)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [golang学习笔记](https://blog.csdn.net/qq_44336275/article/details/111143767)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值