Basic use of channel

1. Piping classification

  • Reading and writing pipeline
  • Read-only pipeline
  • Write only pipes
  • Buffered channel: Specifies the size when creating (default to non buffered channel if not specified)

2. Proper use of pipes

  1. The pipeline can read and write automatically after closing

  2. The write pipeline cannot exceed the capacity cap of the pipeline, and full capacity write will block

  3. When the pipeline is empty, if it is not closed, continuing to read will block the current thread until something is written to the pipeline

  4. m,ok:=<-intChan  //ok is used to check whether the production has been closed. false means it is closed. m is the default value
    

    Generally, the following operations can be used to judge whether the reading is completed. If the writing process does not close the pipeline, it means that there is something else to write

    v,ok:=<-intChan
    if !ok{
    	fmt.Println("Finished reading")
    	break
    }
    

3. Pipeline traversal and access

  • For range access
  • select access (common)

for-range

//Gor range if the pipeline has no data and has not been closed, it will block waiting
	go func() {
		for i:=range c{ //Note that there is no ok here to judge whether it is closed, only one return value
			fmt.Println(i)
		}
	}()

In the following case, for range will block. After one second, print 1, and "closed". If there is no write and it is not closed at the same time, it will block all the time

	ch := make(chan int)	
	go func() {
		time.Sleep(time.Second)
		//close(ch)
		ch<-1
	}()
	go func() {
	for i:=range ch{
		log.Println(i)
	}
   log.Println("Shut down")
	}()
	time.Sleep(time.Hour)

In the following case, the for range will end in a second, and the print "off" will be printed at the same time

	ch := make(chan int)	
	go func() {
		time.Sleep(time.Second)
		close(ch)
		//ch<-1
	}()
	go func() {
		for i:=range ch{
			log.Println(i)
		}
		log.Println("Shut down")
	}()
	time.Sleep(time.Hour)

select

Select randomly selects the non blocked pipes in the case to read or write. If they are blocked, the default statement will be executed. Generally, select will be accompanied by a default statement

	c:=make(chan string,2)
	send:= func(v string) {
		select {
		case c<-v:log.Println("input",v)
		default:log.Println("Buffer full")
		}
	}

	receive:= func() string {
		select {
		case v:=<-c:return v
		default:
			log.Println("Buffer space")
			return ""
		}
	}


	send("h1")
	send("h2")
	send("h3") //Input failure

	log.Println(receive())
	log.Println(receive())
	log.Println(receive()) //Take failure

When the pipeline is closed, select will also succeed. After printing for one second, it will end. There is no writing to the pipeline, so the default value of 0 will be printed at the end

	ch := make(chan int)
	//go func() {
	//	ch <- 1
	//}()
	go func() {
		time.Sleep(time.Second)
		close(ch)
		
	}()
	go func() {
		for {
			time.Sleep(time.Microsecond*500)
			select {
			case v := <-ch:
				log.Println(v)
				return
			default:
				log.Println("etc.")
			}
		}
	}()
	time.Sleep(time.Hour)

4. Blocking condition

1. No shutdown, pipeline element 0, read process blocked

2. If it is not closed and the pipeline element is full, the write process will block, and if there is no buffer pipeline, the write process will block until someone reads it

3. When the pipeline is closed and read after reading is finished, the default null value of the corresponding type of pipeline will be read out. When writing in a closed channel, an error will be reported

	ch:=make(chan int,1)
	ch<-1
	close(ch)

	log.Println(<-ch) //1
	log.Println(<-ch) //0
	log.Println(<-ch)//0
	a,ok:=<-ch
	log.Println(a,ok)//0 false
  1. If the pipeline is closed and written, an error will be reported

  2. No buffering = blocking, buffering = non blocking, no buffering is synchronous, buffering is asynchronous

Like the following non buffered pipeline, if no one reads it, it will be blocked all the time. Only A1 will be printed. If one of the pipelines is read, it will continue to write. For example, if the courier comes to deliver the express, it will only leave after you take the express, or it will be waiting for you to take it

	ch := make(chan int)
	go func() {
		for{
			log.Println("A1")
			time.Sleep(time.Second)
			//close(ch)
			ch<-1
			log.Println("A2")
		}

	}()

What if I set cap to 1?

	ch := make(chan int,1)
	go func() {
		for{
			log.Println("A1")
			time.Sleep(time.Second)
			//close(ch)
			ch<-1
			log.Println("A2")
		}

	}()

Print as follows, you can write a

2020/03/21 20:02:59 A1
2020/03/21 20:03:00 A2
2020/03/21 20:03:00 A1

Keywords: Go

Added by sfw5000 on Sun, 22 Mar 2020 09:53:15 +0200