首页 > 其他 > 详细

Go:channel

时间:2019-05-31 21:27:05      阅读:102      评论:0      收藏:0      [点我收藏+]

一、channel

在 Go 语言里,不仅可以使用原子函数和互斥锁来保证对共享资源的安全访问以及消除竞争状态,还可以使用 channel,通过发送和接收需要共享的资源,在 goroutine 之间做同步。
当一个资源需要在 goroutine 之间共享时,channel 在 goroutine 之间架起了一通道,并提供了确保同步交换数据的机制。声明 channel时,需要指定将要被共享的数据的类型。可以通过 channel 共享内置类型、命名类型、结构类型和引用类型的值或者指针。

基本使用

技术分享图片
package main

import (
    "fmt"
)

func main() {
    // 使用 make 创建 channel
    // 方式1
    var intChan chan int
    intChan = make(chan int, 3)
    // 方式2
    // intChan := make(chan int, 3)

    fmt.Printf("aChan的值:%v\n", intChan)             // 0xc000086000
    fmt.Printf("aChan本身的地址:%p\n", &intChan)     // 0xc000080018

    // 向管道发送值(注意给channel放入数据时,不能超过其容量)
    intChan <- 10
    intChan <- 20
    fmt.Printf("aChan的len:%v\n", len(intChan)) // 2
    fmt.Printf("aChan的cap:%v\n", cap(intChan)) // 3

    // 从管道中读取数据
    int1 := <- intChan
    int2 := <- intChan
    fmt.Println(int1, int2) // 10 20
}
示例1
技术分享图片
package main

import (
    "fmt"
)

type Cat struct {
    Name string
    Age int
}

func main() {
    // 定义一个存放任意数据类型的管道3个数据
    allChan := make(chan interface{}, 3)
    allChan <- 10
    allChan <- "pd"
    cat := Cat{"tom", 10}
    allChan <- cat
    // 如果希望获得到管道中的第三个元素,则需先将前2个推出
    <- allChan
    <- allChan
    newCat := <- allChan
    fmt.Printf("newCat=%T , newCat=%v\n", newCat, newCat)
    // fmt.Println(newCat.Name)     // 编译不通过,错误
    fmt.Println(newCat.(Cat).Name)    // 使用类型断言,正确
}
示例2

channel 使用注意事项:

  1. channel中只能存放指定的数据类型;
  2. channel的数据放满后,就不能在放入了;
  3. 如果从 channel 取出数据后,就可以继续放入了;
  4. 在没有使用 goroutine 的情况下,如果 channel 数据被取完了,再取,就会报 dead lock。

二、关闭 channel

关闭 channel 非常简单,直接使用Go语言内置的close()函数即可:
func main() {
	intChan := make(chan int, 3)
	intChan <- 10
	intChan <- 20
	// 关闭 channel
	close(intChan)
	// 关闭 channel 后,无法将数据写入到 channel 中,读取数据是可以的
	num := <- intChan
	fmt.Println(num) // 10
}

三、遍历 channel

channel 支持 for-range 的方式进行遍历:

  1. 在遍历时,如果 channel 没有关闭,则会出现 deadlock 错误;
  2. 在遍历时,如果 channel 已经关闭,则会正常遍历数据,遍历完后,就会退出遍历。
技术分享图片
package main

import "fmt"

func main() {
    ch := make(chan int, 3)
    ch <- 10
    ch <- 20
    ch <- 30
    // 关闭 channel
    close(ch)
    // 遍历 channel
    for v := range ch {
        fmt.Println(v)
    }
}
View Code

 

 

1

  

Go:channel

原文:https://www.cnblogs.com/believepd/p/10957377.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!