GoLang 并发Goroutine&Channel(二)
1.channel通道初识
func main() {
var ch1 chan bool
ch1 = make(chan bool)
go func() {
for i := 0; i < 10; i++ {
time.Sleep(time.Second)
fmt.Println(i)
}
fmt.Println("结束...")
ch1 <- true
}()
fmt.Println("channel之前...")
data := <-ch1
fmt.Println(data)
fmt.Println("main over...")
}
func main() {
ch := make(chan int)
go func() {
fmt.Println("子goroutine执行...")
time.Sleep(time.Second * 3)
data := <-ch
fmt.Println("data:", data)
}()
ch <- 200
fmt.Println("main over...")
}
2.关闭通道和通道上的范围循环
(一)for循环的方式
func main() {
ch1 := make(chan int)
go SendData(ch1)
for {
time.Sleep(time.Second)
v, ok := <-ch1
if !ok {
fmt.Println("结束...")
break
}
fmt.Println(v)
}
fmt.Println("main over...")
}
func SendData(ch chan int) {
defer close(ch)
for i := 0; i < 10; i++ {
ch <- i
}
}
(二)for range的方式
func main() {
ch := make(chan int)
go SendData2(ch)
for v := range ch {
fmt.Println(v)
}
fmt.Println("main over...")
}
func SendData2(ch chan int) {
defer close(ch)
for i := 0; i < 10; i++ {
time.Sleep(time.Second)
ch <- i
}
}
3.缓存通道
- 相较于非缓冲通道,缓冲通道可以设置容量大小,只有达到容量的大小,读取和发送才会阻塞
func main() {
ch := make(chan int, 4)
go SendData3(ch)
for v := range ch {
fmt.Println("\t读取的数据:", v)
}
fmt.Println("main over...")
}
func SendData3(ch chan int) {
defer close(ch)
for i := 0; i < 10; i++ {
ch <- i
fmt.Println("发送的数据:", i)
}
}
4.单向通道
func main() {
ch1 := make(chan string)
done := make(chan bool)
go sendData(ch1, done)
data := <-ch1
fmt.Println(data)
ch1 <- "我是main goroutine..."
<-done
}
func sendData(ch chan string, done chan bool) {
ch <- "我是func goroutine..."
data := <-ch
fmt.Println(data)
done <- true
}
- 创建单项的通道(读,写)
- 单项通道一般作为函数的形参使用,传入的实参还是用双向通道
func main() {
ch1 := make(chan int)
go fun1(ch1)
data := <-ch1
fmt.Println(data)
go fun2(ch1)
ch1 <- 999
fmt.Println("main over...")
}
func fun1(ch chan<- int) {
ch <- 100
fmt.Println("func1结束")
}
func fun2(ch <-chan int) {
data := <-ch
fmt.Println(data)
fmt.Println("func2结束")
}
5.time包中的通道函数
func main() {
timer := time.NewTimer(3 * time.Second)
ch := timer.C
fmt.Println(time.Now())
fmt.Println(<-ch)
}
func main() {
timer := time.NewTimer(5 * time.Second)
go func() {
<-timer.C
fmt.Println("完成...")
}()
time.Sleep(3 * time.Second)
timer.Stop()
fmt.Println("main over...")
}
func main() {
ch := time.After(3 * time.Second)
fmt.Println(time.Now())
fmt.Println(<-ch)
}
6.select语句
- 如果没有default语句等待通信(阻塞),否则直接执行default语句
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
time.Sleep(3 * time.Second)
ch1 <- 100
}()
go func() {
ch2 <- 200
}()
select {
case <-ch1:
fmt.Println("case1 中的语句...")
case <-ch2:
fmt.Println("case2 中的语句...")
}
fmt.Println("main over...")
}