chan在go中是一个通道有可读可写的chan,也存在只读只写的chan,通过共享内存而实现通信
chan 注意点:
在关闭chan后再关闭chan 会出现panic
关闭chan后可以继续进行取值,取完后可以再取但都是对应类型的0值。
可以通过 v,ok:=<-ch 来判断是否取完了 取完了ok为false
也可以通过for range 来取值
for v:= range ch{
fmt.Printf("the data is %d",v)
}
for {
v,ok:=<-ch
if !ok{
fmt.Printf("the data is %d",v)
fmt.Println("取完了")
}
fmt.Printf("the data is %d",v)
}
chan需要初始化:
//开辟缓冲区为20的chan
ch1:=make(chan int,20)
//无缓冲区的chan
ch2:=make(chan int)
//只能向chan内写
ch3:=make( chan<-int,20)
ch3 := make(chan<- int, 20)
ch3 <- 10
ch3 <- 20
fmt.Println(len(ch3))
//只能从chan内读
ch4:=make(ch<-chan int,20)
chan 不给缓冲区无法放入值,在某些情况
但是你可以开另外的goroutine来取值,快递原理,不在家储物柜没位置,无法放入快递(放值),快递柜满了,有人来取则可以取值
产生数据并开24个线程消耗数据,并将数据的每一位的和传到主goroutine进行打印
goroutine
package main
import (
"fmt"
"math"
"math/rand"
"sync"
)
//generate int64 number
func generateRandomNumber(ch chan<- int64) {
// var i int64
for {
ch <- int64(rand.Int63())
}
}
//get the sum of all digit of input number
// 获取输入数的每一位的和
func GetSum(s int64) int64 {
strNum := fmt.Sprintf("%d", s)
lenNum := len(strNum)
var sumOfAllDigit int64 = 0
for i := lenNum - 1; i >= 0; i-- {
temp := s / int64(math.Pow(10, float64(i)))
fmt.Println(temp)
s = s % int64(math.Pow(10, float64(i)))
sumOfAllDigit += temp
}
fmt.Println("sum is ", sumOfAllDigit)
return sumOfAllDigit
}
//24个线程消费生成的数据
func JobChan(wg *sync.WaitGroup, ch chan int64) (sumInfo chan int64) {
// var chresult chan<- int64
sumInfo = make(chan int64, 3000)
for i := 0; i < 24; i++ {
wg.Add(1)
go func(ch <-chan int64) {
for {
temp := <-ch
fmt.Println(temp)
sum := GetSum(temp)
fmt.Println("temp is ", temp)
fmt.Println("sum is ", sum)
sumInfo <- sum
}
wg.Done()
}(ch)
}
return
}
func main() {
wg := sync.WaitGroup{}
chOrigin := make(chan int64, 30000)
// ch1 := make(chan int64, 300)
go generateRandomNumber(chOrigin)
chSum := JobChan(&wg, chOrigin)
for v := range chSum {
fmt.Println("*&*&*&*&*&***&**", v)
}
// wg.Wait()
// select {}
}