The sender of the chan queue waits for the receiver to process the result

Receive elements from a nil channel, the current goroutine will block

Send elements to a nil channel, the current gotoutine will also block

Sending an element to a closed channel will cause a runtime panic, even if the send operation is blocked because the channel is full.

 

When multiple goroutines send element blocking to the same full channel, when the channel has free space, the earliest blocked goroutine will be woken up first.

When multiple goroutines receive element blocking from the same empty channel, when the channel has elements, the earliest blocked goroutine will be woken up first.

Go only wakes up one goutine at a time.

 

The value sent by the sender to the channel is copied, and the receiver always receives a copy of the value.

The value passed through the channel will be copied at least once and at most twice.

For example, when copying once and sending elements to an empty channel, and there is already at least one receiver waiting to receive, the channel will bypass its own buffer queue and directly copy to the earliest receiver waiting to receive.

Such as: copy twice, receive elements from a full channel, and at least one sender is waiting for sending, the channel will copy the earliest entered element in the buffer queue to the receiver, and then send the earliest sender data Copy to an empty location.

 

When the receiver receives a value of value type from the channel, the modification of this value will not affect the source value held by the sender;

When the receiver receives a reference type value from the channel, the modification of the value will affect the source value held by the sender;

package main

import (
	"fmt"
	//"time"
)

type dataItem struct {
	curl     string
	paramReq interface{}
	resp     chan error
}

type metaset struct {
	key   string
	value string
	uid   string
	path  string
}

var dataChan = make(chan interface{}, 1)
/*
syncChan1和syncChan2的元素类型都是 struct{},struct{}代表不含任何字段的结构体类型(空结构体)

空结构体变量不占内存空间,所以所有该类型的变量都拥有相同的内存地址。

建议用于传递信号的通道都用struct{}作元素类型,除非需要传递更多的元素。
*/
func main() {
	syncChan := make(chan struct{}, 2)
	go func() {
		for {
			if elem, ok := <-dataChan; ok {
				if elem, ok := elem.(dataItem); ok {
					elem.resp <- nil
					fmt.Printf("elem:%v\n", elem)
					fmt.Printf("elem.paramReq:%v\n", elem.paramReq)
				} else {
					fmt.Printf("error")
				}
			} else {
				break
			}
		}
		fmt.Println("stopped.[receiver]")
		syncChan <- struct{}{}
	}()

	go func() {
		meta := metaset{key: "key1", value: "value1", uid: "00", path: "/root/dir1"}
		data := &dataItem{curl: "/api/test", paramReq: meta, resp: make(chan error, 1)}
		for i := 0; i < 5; i++ {
			dataChan <- *data
			//time.Sleep(time.Second)
			fmt.Printf("The count map:%v.[sender]\n", data)
			res := <-data.resp
			fmt.Println("res:", res)
		}
		close(dataChan)
		syncChan <- struct{}{}
	}()
	<-syncChan
	<-syncChan

}

result:

elem:{/api/test {key1 value1 00 /root/dir1} 0xc042034120}
elem.paramReq:{key1 value1 00 /root/dir1}
The count map:&{/api/test {key1 value1 00 /root/dir1} 0xc042034120}.[sender]
res: <nil>
elem:{/api/test {key1 value1 00 /root/dir1} 0xc042034120}
elem.paramReq:{key1 value1 00 /root/dir1}
The count map:&{/api/test {key1 value1 00 /root/dir1} 0xc042034120}.[sender]
res: <nil>
elem:{/api/test {key1 value1 00 /root/dir1} 0xc042034120}
elem.paramReq:{key1 value1 00 /root/dir1}
The count map:&{/api/test {key1 value1 00 /root/dir1} 0xc042034120}.[sender]
res: <nil>
elem:{/api/test {key1 value1 00 /root/dir1} 0xc042034120}
elem.paramReq:{key1 value1 00 /root/dir1}
The count map:&{/api/test {key1 value1 00 /root/dir1} 0xc042034120}.[sender]
res: <nil>
elem:{/api/test {key1 value1 00 /root/dir1} 0xc042034120}
elem.paramReq:{key1 value1 00 /root/dir1}
The count map:&{/api/test {key1 value1 00 /root/dir1} 0xc042034120}.[sender]
res: <nil>
stopped.[receiver]

 

 

Published 127 original articles · Likes 24 · Visits 130,000+

Guess you like

Origin blog.csdn.net/Linzhongyilisha/article/details/104245080