## 简明笔记:Goroutine &channel
> f() // call f();wait for it to return
>
> go f() //create a new goroutine that calls f();don't wait
## Goroutine
调用普通函数,等待函数返回值返回。
创建一个goroutine,调用函数,不会等待其函数返回值返回。
```go
package main
import (
"fmt"
)
func helloworld(){
fmt.Println("goroutine...")
}
func main() {
go helloworld() //在函数面前加上关键字Go,创建一个goroutine。
fmt.Println("执行结束...")
}
输出结果:
执行结束
```
执行速度很快,这里看不到helloworld()函数的输出,所以验证了我上面所说的。don't wait
```go
package main
import (
"fmt"
"time"
)
func fun(){
for i:=0;i<5;i++{
time.Sleep(500*time.Millisecond) // 等待0.5秒
fmt.Println(i)
}
}
func main() {
go fun()
time.Sleep(1*time.Second) // 等待1秒
fmt.Println("执行结束...")
}
输出结果:
0
1
执行结束...
```
多个goroutine 并行
```go
func fun(){
for i:=0;i<5;i++{
time.Sleep(500*time.Millisecond) // 等待0.5秒
fmt.Println(i)
}
}
func run(){
fmt.Println("run function")
}
func main() {
go fun()
go run()
time.Sleep(2*time.Second) // 等待2秒
fmt.Println("执行结束...")
}
输出结果:
run function
0
1
2
执行结束...
```
## 通道(channel)
```go
var ch chan int // 声明一个channel
ch :=make(chan int) //定义一个channel
ch <-value //向ch写入数据。通常会导致程序阻塞,知道有其它goroutine从这个channel中读取数据
value := <- ch //读取ch的数据。如果channel之前没有写入数据,那么从channel中读取数据也会导致阻塞,直到channel被写入数据为止。
```
举个栗子
```go
var ch chan int //定义为全局
func ready(w string){
time.Sleep(1*time.Second)
fmt.Println(w,"is ready")
ch <- 1 //发送1到channel ch
}
func main() {
ch = make(chan int)
go ready("Potato")
fmt.Println("I'm waiting")
<-ch
}
输出结果:
I'm waiting
Potato is ready
```
### 指定channel(通道)缓存
#### 无指定缓存大小
```go
package main
import (
"fmt"
"time"
)
func main() {
c := make(chan int)
go send(c)
go recv(c)
time.Sleep(3 * time.Second)
close(c)
}
func send(c chan <- int){
for i:=0;i<10;i++{
fmt.Println("发送 >>>",i)
c <- i
}
}
func recv(c <-chan int){
for i:=range c{
fmt.Println("接收 <<<",i)
}
}
输出结果:
发送 >>> 0
发送 >>> 1
接收 <<< 0
接收 <<< 1
发送 >>> 2
发送 >>> 3
接收 <<< 2
接收 <<< 3
发送 >>> 4
接收 <<< 4
```
没有指定缓存的通道,只尊顺一进一出的原则(默认是无缓存,即同步),
往channel 发送数据后,这个数据如果没有取走,channel是阻塞的,也就是不能继续向channel 里面发送数据。因为上面代码中,我们没有指定channel 缓冲区的大小,默认是阻塞的。
### 带有缓存的channel
```go
func main() {
c := make(chan int,10)
go send(c)
go recv(c)
time.Sleep(3 * time.Second)
close(c)
}
func send(c chan <- int){
for i:=0;i<5;i++{
fmt.Println("发送 >>>",i)
c <- i
}
}
func recv(c <-chan int){
for i:=range c{
fmt.Println("接收 <<<",i)
}
}
输出:
发送 >>> 0
发送 >>> 1
发送 >>> 2
发送 >>> 3
发送 >>> 4
接收 <<< 0
接收 <<< 1
接收 <<< 2
接收 <<< 3
接收 <<< 4
```
有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道(即异步)。
通道会阻塞发送和接收动
作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区
容纳被发送的值时,发送动作才会阻塞。
> 关注公众号:面向奶酪
获取最新文章
有疑问加站长微信联系(非本文作者))