### chanel类型
用于多个协程之间的通信,channel是一种特殊类型,和map类似
> **var 通道变量 chan 通道类型**
>
定义channel时,也需要定义发送到channel的值的类型,可以使用make()函数创建
> **make(chan Type) ,等价于 make(chan Type, 0)**
> **make(chan Type, capacity)**
> Type,类型
>
当capacity (容量) 为0时,channel是无缓冲堵塞读写的,当capacity大于0时,channel是有缓冲,非堵塞的,直到写满capacity个元素才堵塞写入。
channel 通过 "<-" 来接收和发送数据
默认channel收发数据都是堵塞的
```
channel <- value //发送value到channel
<- channel //接收并将其丢弃
x := <- channel //从channel中接收数据,赋值给x
x, ok = <- channel //从channel中接收数据赋值给x,检查通道是否关闭将此状态赋值给ok
```
```
package main
import (
"fmt"
"time"
)
func main() {
// 创建通道
ch := make(chan string)
go func() {
// 打印通道接收的 值
fmt.Println(<-ch)
}()
// 发送 hello 到到通道 ch
ch <- "hello"
time.Sleep(time.Second)
}
结果:
hello
```
### 缓冲机制
无缓冲通道,是指接收前没有能力保存任何值的通道
> **make(chan Type),等价于 make(chan Type, 0)**
>
无缓冲通道ch,只有当接收者接收到数据,发送者才能继续发送
```
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 0)
go func() {
for i := 0; i < 3; i++ {
fmt.Printf("长度len() = %v, 容量cap(ch)=%v\n", len(ch), cap(ch))
// 把 i 发送给通道 ch
ch <- i
}
}()
for i := 0; i < 3; i++ {
time.Sleep(time.Second)
// 打印接收的通道 ch
fmt.Println(<-ch)
}
}
结果:
长度len() = 0, 容量cap(ch)=0
0
长度len() = 0, 容量cap(ch)=0
1
长度len() = 0, 容量cap(ch)=0
2
```
有缓存通道,是指被接收前能储存一个或者多个值的通道
>**make(chan Type, capatity)**
```
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 3)
go func() {
for i := 0; i < 3; i++ {
fmt.Printf("长度len() = %v, 容量cap(ch)=%v\n", len(ch), cap(ch))
// 把 i 发送给通道 ch
ch <- i
}
}()
for i := 0; i < 3; i++ {
time.Sleep(time.Second)
// 打印接收的通道 ch
fmt.Println(<-ch)
}
}
结果:
长度len() = 0, 容量cap(ch)=3
长度len() = 1, 容量cap(ch)=3
长度len() = 2, 容量cap(ch)=3
0
1
2
```
### close 和range
close和range 让通道停止不必要的等待
.
**close**
channel不像文件可以经常关闭,只有当你没有需要发送的数据时,或者想结束range循环之类的,才会关闭
关闭后无法再错向channel发送数据,但是可以从channel接收
对于nil channel(空通道)无论接收还是发送都会堵塞
```
package main
import "fmt"
func main() {
// 创建一个通道
ch := make(chan int, 3)
go func() {
for i := 0; i < 3; i++ {
fmt.Printf("长度len() = %v, 容量cap(ch)=%v\n", len(ch), cap(ch))
// 发送i给通道
ch <- i
}
// 关闭通道
close(ch)
}()
for i := 0; i < 3; i++ {
// 如果通道里面有值 ok 就等于 true 没有了就是false 执行else
if val, ok := <-ch; ok == true {
fmt.Println(val)
} else {
return
}
}
}
结果:
长度len() = 0, 容量cap(ch)=3
长度len() = 0, 容量cap(ch)=3
长度len() = 1, 容量cap(ch)=3
0
1
2
```
.
**range遍历通道**
```
for data:= range ch{
}
```
```
package main
import "fmt"
func main() {
// 创建一个通道
ch := make(chan int, 3)
go func() {
for i := 0; i < 3; i++ {
fmt.Printf("长度len() = %v, 容量cap(ch)=%v\n", len(ch), cap(ch))
// 发送i给通道
ch <- i
}
// 关闭通道
close(ch)
}()
// 遍历通道
for data := range ch {
fmt.Println(data)
}
}
结果:
长度len() = 0, 容量cap(ch)=3
长度len() = 0, 容量cap(ch)=3
长度len() = 1, 容量cap(ch)=3
0
1
2
```
- 安装开发环境
- 安装开发环境
- 安装详细教程
- 引入包
- Go语言基础
- 基本变量与数据类型
- 变量
- 数据类型
- 指针
- 字符串
- 代码总结
- 常量与运算符
- 常量
- 运算符
- 流程控制
- if判断
- for循环
- switch分支
- goto跳转
- 斐波那契数列
- Go语言内置容器
- 数组
- 切片
- 映射
- 函数
- 函数(上)
- 函数(中)
- 函数(下)
- 小节
- 包管理
- 结构体
- 结构体(上)
- 结构体(中)
- 结构体(下)
- 小节
- 错误处理
- 错误处理
- 宕机
- 错误应用
- 小节
- 文件操作
- 获取目录
- 创建和删除目录
- 文件基本操作(上)
- 文件基本操作(中)
- 文件基本操作(下)
- 处理JSON文件
- 接口与类型
- 接口的创建与实现
- 接口赋值
- 接口嵌入
- 空接口
- 类型断言(1)
- 类型断言(2)
- 小节
- 并发与通道
- goroutine协程
- runtime包
- 通道channel
- 单向通道channel
- select
- 线程同步
- 多线程的深入学习
- http编程
- http简介
- Client和Request
- get请求
- post请求
- 模块函数方法
- 模块
- fmt库,模块
- 项目练习
- 爬虫:高三网
- 爬虫:快代理
- 爬虫:快代理2
- 多线程:通道思路
- 多线程爬虫:快代理