This is a creation in Article, where the information may have evolved or changed. # #channel的用法channel是golang中很重要的概念, with Goroutine is the key for Golang to facilitate concurrent programming. Channel is actually the traditional language blocking message queue, can be used to do different goroutine between the message delivery, because Goroutine is lightweight thread can be in the language level scheduling, so channel in Golang is also used to synchronize Goroutine. The general channel is declared as: Var channame chan elementtypeelementtype Specifies the type of element that this channel can pass. Defining a channel is also straightforward, using the built-in function make (): ch: = Makes (chan int,buffersize)//buffersize is the size of the buffer, can not be passed this value represents the channel # # # without buffer Message passing a channel with buffers is typically used for message passing between different goroutine. The most classic explanation is the producer-consumer. The producer writes data to the channel, and if the channel buffer is full, the producer is blocked until the consumer consumes the data in the buffer to be awakened. The consumer reads the data from the channel, and if there is no data in the buffer, the consumer blocks until the producer writes the data to be awakened. Suppose we have 30 students doing their homework, and a teacher corrects the homework after finishing the homework. What do we do with go, we first define a buffer homework Chan (the size of the buffer is the same as the number of students, mainly to prevent students from blocking when the job is submitted), the student finishes the job to send data to the Hwchan, The teacher waits for data in the Hwchan to take out the student's homework and correct it. ' Const STUDENTNUM = type homework struct {}function student (Hwchan Chan homework) {//Student submit job Hwchan <-homework{}} function teacher (Hwchan Chan homework) {//The teacher takes out 30 students ' homework to correct for i:=0;i<studentnum;i++ {hw: = <-Hwchan}}func main () {HW Chan: = Make (chan homework,30)//Each student starts a goroutine, the student does the homework alone, finishes the assignment and submits it to Hwchan for I: =0;i<studentnum;i++ {Go student (Hwchan)}//teacher opens a goroutine to correct the student assignment go Teacher (Hwchan) time. Sleep (5*time. Second} "* * one-way channel**student only need to write data to the channel, not to read the data from the channel, but in the Func student (Hwchan Chan homework) This function student actually has the permission to read the data from the channel, can restrict this function can only fetch the data but cannot write the data? One-way channel is to solve this problem: chan<-ElementType says the data can only be written to the channel <-chan ElementType Indicates that data can only be read from this channel we change the parameters of the student function to func student (Hwchan chan<-homework) It is possible to convert the bidirectional channel of Hwchan into a write-only one-way channel to the student function. Similarly, the parameter of the teacher function becomes function teacher (Hwchan <-chan homework), which specifies that the data can only be read from this channel within the teacher function. # # #同步main函数最后一段代码 time. Sleep (5*time. Second), mainly in order to prevent the main function is located in the master Goroutine no teacher where the Goroutine corrected 30 students to quit the job, the main goroutine exit led to the entire program exit. Sleep 5 Seconds is because the teacher will definitely be able to finish the homework in five seconds, but if more than 5s is still a problem. We now have a new demand, the main goroutine opened a teacher goroutine, the main goroutine need to wait for teacher to finish correcting 30 students to continue to work. Then we need to create another channel for the synchronization between the Goroutine. "Func main () {Hwchan: = Make (chan homework,30) Exitchan: = Make (chan struct{}) for I:=0;i<s tudentnum;i++ {Go student (Hwchan)}go Teacher (Hwchan,exitchan) <-exitchan} function teacher (Hwchan Chan Homework,exitchan Chan struct{}) {for i:=0;i<studentnum;i++ {hw: = <-Hwchan}close (Exitchan)} ' main goroutine will block at <-exitchan until teacher corrects 30 students ' assignments, Then close (Exitchan), <-exitchan returned when teacher had finished correcting the student's homework, the program quit there is no problem. > As to why the definition Exitchan for Chan struct{} instead of Chan int{} is because Chan struct{} does not need to occupy any memory space var s struct{}fmt. Println (unsafe. Sizeof (s))///Prints 0# #特殊状态的channel # # # uninitialized channel ' var ch chan int ch<-1//block Forever <-CH//block Close Forever (CH)//panic close of nil channel "reads and writes data into an uninitialized channel, causing the goroutine to block forever. > As to why it should be blocked forever rather than panic, I have not found a more convincing answer at the moment. # # # Closed channel+ writing data to the closed channel will cause panic. + Close a closed channel will cause panic. + read data from a closed channel does not cause panic to return 0 values of that data type ' ch: = make (chan int) close (ch) i <-ch//i =0 Close (CH)//pan Ic:close of closed channel "but we can't tell that the channel is closed because it reads a value of 0 from a channel, because the 0 value may also be normal data. ' ch: = make (chan int) ch<-0//write to channel 0 I <-cH//Although the data read from the channel is 0, it cannot be judged that the channel has been closed. Read data from the channel support two return worth form I,ok <-CH OK is a bool value. + read data from closed channel with cache "ch: = Make (chan int,3) ch <-1 ch <-0 ch <-3 i,ok <-ch//i for 1,ok for T Rue (channel not closed) Close (CH) j,ok <-ch//j is 0,ok true (the channel is closed, but there is still data in the cache, J is 0 can not determine the channel is closed) M,ok <- CH//m is 3 not 0,ok is true (although the channel is closed but there is still data in the cache) N,ok <-ch//n is 0,ok to False (indicates that the channel is closed and there is no data in the buffer, n is assigned a value of 0 of that type) " After the channel is closed, false is not immediately the second result of the corresponding receive operation, but is not done until the receiving end has received all the element values in the channel. This ensures that the data sent to the channel before the channel is closed can be read by the consumer. There is also a simpler way to read the elements in the channel ' for Elem <-range CH {}//When CH is closed and the buffered data is removed, the for loop will exit ' # # # Source Implementation '/A channel is actually a A Hchan variable type Hchan struct {buf unsafe. Pointer//Pointer to buffer, if buffer is empty, nildataqsiz uint//Buffer size Elemtype *_type//Element typeelemsize UInt16//single element siz E//sendx RECVX implements a FIFO array list sendx UINT//Send INDEXRECVX UINT//Receive indexqcount UINT//buffer buffers in number of elements recvq WAITQ// Consumer wait list SENDQ WAITQ//producer Wait ListClosed UInt32//identifies if the channel is closed lock mutex}//Initializes a channel func Makechan (t *chantype, size Int64) *hchan {elem: = T.elemvar c *hchanif Size = = 0 {//Initialize a CHANNELC = (*hchan) without buffers (MALLOCGC (hchansize+uintptr (size) *uintptr (elem.size), nil, Flagn OScan)} else {//initialize a channel with buffer, need to create an array to do buffer c = new (Hchan) C.buf = NewArray (Elem, uintptr (size))}c.elemsize = UInt16 (elem.size) C.elemtype = Elemc.dataqsiz = UINT (size) return c}//write data to channel func chansend (t *chantype, C *hchan, EP unsafe . Pointer, block bool, CALLERPC uintptr) bool {if c = = nil {//write data to an uninitialized channel (nil) causes Goroutine to permanently block Gopark (nil, nil, "Chan Send (Nil chan) ", Traceevgostop, 2) throw (" unreachable ")}//lock, so multiple gorotuine to read and write data to a channel at the same time is no problem lock (&c.lock )//To a closed channel write data will cause PANICIF c.closed! = 0 {unlock (&c.lock) Panic ("Send on Closed channel")}//according to the size of the buffer dataqsiz, Determine if there is a buffer if C.dataqsiz = = 0 {//try to remove a waiting goroutinesg from the recvq wait queue: = C.recvq.dequeue () if SG! = Nil {//Find a goroutine waiting to read the data ( Consumer), the element to be written directly to (copy) this goroutine, and then theGet the element Goroutine set to the Ready state unlock (&c.lock) RECVG: = SG.G//RECVG point to the next consumer syncsend (c, SG, EP)//The element to be written directly to (copy) this consumer G Oready (RECVG, 3) return true}//If there is not a waiting goroutine in Recvq, then the element to be written is saved in the structure of the goroutine that is currently executing the write, The current goroutine is then enqueued into SENDQ and suspended, waiting for someone to read the element before it wakes Mysg: = Acquiresudog () Mysg.elem = EP//producer saves data C.sendq.enqueue (MYSG) Goparkunlock (&c.lock, "Chan send", Traceevgoblocksend, 3) Unlock (&c.lock) return true}//if the channel with the buffer, The producer waits for free space in the buffer to hold the data produced by the producer//Qcount is the amount of data in the buffer, Dataqsiz is the amount of data that can be stored for futile: = byte (0); C.qcount >= C.dataqsiz; Futile = tracefutilewakeup {//If the buffer does not have free space, the current goroutine is enqueued into SENDQ and suspended waiting. MYSG: = Acquiresudog () Mysg.elem = Nilc.sendq.enqueue (mysg) goparkunlock (&c.lock, "Chan send", traceevgoblocksend| Futile, 3) unlock (&c.lock)}//if the buffer has free space, append the element to the buffer, and then try to remove a waiting recvq from the consumer wait queue goroutine to start the read operation ( Typedmemmove (C.elemtype, Chanbuf (c, C.sendx), EP) c.sendx++if C.sendx = = C.dataqsiz {C.sendx = if there are goroutine waiting to be read in RECVQ) 0}c.qcount++//wake up a waiting RECEIVERSG: = C.recvq.dequeue () if SG! = Nil {RECVG: = Sg.gunlock (&c.lock) Goready (RECVG, 3)} else {unlock (&c.lock)}return true} The process of reading data from the channel and the writing process almost no longer code "# #参考资料channel in Go ' Runtime (Skoo blog, dry)" Go language Programming "go concurrent programming combat
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.
A Free Trial That Lets You Build Big!
Start building with 50+ products and up to 12 months usage for Elastic Compute Service