This is a creation in Article, where the information may have evolved or changed.
What's wasting today is tomorrow to those who died yesterday; What's the future of hate now?
What you are wasting today is the tomorrow that the man who died yesterday expects, and what you dislike is now the future you will never go back to.
Buffered Channel
The channel we talked about before is not buffered, and both sending and receiving can cause blocking.
The buffer channel is characterized by the acceptance of the block only when the send to buffer is full.
How to create: ch:= make (Chan Type, capacity)
Capacity capacity, when capacity = 0 o'clock, is an unbuffered channel, usually omitted.
package mainimport ("fmt")func main() {ch := make(chan string, 2)ch <- "naveen"ch <- "paul"fmt.Println(<- ch)fmt.Println(<- ch) // 注释此行,会不会deadlock???}
Following this example, consider carefully and help to understand the buffered channel:
package mainimport ( "fmt" "time")func write(ch chan int) { for i := 0; i < 5; i++ { ch <- i fmt.Println("successfully wrote", i, "to ch") } close(ch)}func main() { ch := make(chan int, 2) go write(ch) time.Sleep(2 * time.Second) for v := range ch { fmt.Println("read value", v,"from ch") time.Sleep(2 * time.Second) }}
Explain:
When the main process creates a channel with a capacity of 2, then loops through the goroutine, writes two times, goroutine blocks, and the main thread also enters sleep, and when range starts receiving, Goroutine Discovery can continue writing.
Output:
successfully wrote 0 to chsuccessfully wrote 1 to chread value 0 from chsuccessfully wrote 2 to chread value 1 from chsuccessfully wrote 3 to chread value 2 from chsuccessfully wrote 4 to chread value 3 from chread value 4 from ch
Write two times at the beginning because the channel capacity is 2 and can be written without having to read it.
Last two reads, because when the range is read once, Goroutine writes once, so the channel always holds 2 data.
Concept: Length and capacity
Capacity refers to the maximum storage length of the channel. Length refers to the length of the data being queued in the current channel.
Code Description:
package mainimport ( "fmt")func main() { ch := make(chan string, 3) ch <- "数据1"ch <- "数据2" //容量为3, 但是其中数据只有2个 fmt.Println("capacity is", cap(ch)) //数据长度为2 fmt.Println("length is", len(ch)) //读取一次 fmt.Println("read value", <-ch) //数据长度为1, 但是容量还是3 fmt.Println("new length is", len(ch)) }
Output:
capacity is 3length is 2read value 数据1new length is 1
Waitgroup
Work pool implementation is inseparable from Waitgroup, the following talk about Warigroup.
If you have three goroutine in a main thread, to get the output of these three goroutine, you need to block the main thread with Waitgroup and wait for all goroutine to end.
package mainimport ("fmt""sync""time")func ProcessEcho( i int , w *sync.WaitGroup){fmt.Println("协程", i , "开始")time.Sleep(1*time.Second)fmt.Println("协程", i , "结束")w.Done()}func main(){var w sync.WaitGroupMax := 10for i:= 0; i<Max ;i++ {w.Add(1)go ProcessEcho(i, &w)}w.Wait()fmt.Println("main执行完成并退出。")}
Explain:
Main process Start 10 waitgroup, each day to start the high-speed to add a listener, each goroutine end is marked once the end. The main thread waits for all tokens to complete, ending blocking.
Note the point:
1. Why is the W pointer used in Go Processecho?!
2. The output of the goroutine is not regular.
Look at the work pool implementation:
Package Mainimport ("FMT" "Sync" "Time")//Task structure type job struct {ID Intrandomno int}//accept data structure type Result struct {Job Jobsumofdigits Int}var jobs = Make (Chan Job, ten) var results = make (chan Result, Ten) func digits (number int) int {TIME.S Leep (2 * time. Second) return number}func worker (i int, WG *sync. Waitgroup) {for job: = Range jobs {output: = Result{job, digits (i)}results <-OUTPUT}WG. Done ()}func createworkerpool (noofworkers int) {var wg sync. Waitgroupfor I: = 0; i < noofworkers; i++ {WG. ADD (1) Go Worker (I,&WG)}WG. Wait () Close (results)}func allocate (noofjobs int) {for i: = 0; i < noofjobs; i++ {randomno: = ijob: = Job{i, Randomno}jo BS <-Job}close (jobs)}func result (done chan bool) {for result: = Range results {FMT. PRINTF ("Job ID%d, input random no%d, sum of digits%d\n", result.job.id, Result.job.randomno, result.sumofdigits)}done <-True}func Main () {startTime: = time. Now () Noofjobs: = 12//Task number go allocate (noofjobs) Done: = Make (chan bool) go result (done) NOOFWOrkers: = 3//performer Createworkerpool (noofworkers) <-doneendtime: = time. Now () diff: = endtime.sub (startTime) fmt. PRINTLN ("Total Time Taken", diff.) Seconds (), "Seconds")}