This is a creation in Article, where the information may have evolved or changed.
1, remember once gorountine caused by the leakage
Use of Https://github.com/deckarep/golang-set in the project this three-party package caused a gorountine leak. Let's take a look at the iterator settings for this package, as follows:
Package mapset//Iterator defines a Iterator over a set, its C channel can is used to range over the set ' s//Elements.typ E Iterator struct {C <-chan interface{}stop Chan struct{}}//stop stops the Iterator, no further elements would be r Eceived on C, C'll be Closed.func (i *iterator) Stop () {//allows for stop () to be called Multiple times//(Close () pani CS when called on already closed channel) defer func () {Recover ()} () Close (i.stop)//exhaust any remaining elements.for rang e I.C {}}//newiterator returns a new Iterator instance together with its item and stop Channels.func Newiterator () (*iter Ator, chan<-interface{}, <-chan struct{}) {Itemchan: = Make (chan interface{}) Stopchan: = Make (chan struct{}) return &iterator{c: Itemchan,stop:stopchan,}, Itemchan, Stopchan}
In this way, the code to provide the API outward is as follows:
Func (set *threadsafeset) Iterator () *iterator {Iterator, ch, stopch: = Newiterator () go func () {set. Rlock () l:for elem: = Range Set.s {Select {case <-stopch:break Lcase ch <-elem:}}close (CH) set. Runlock ()} () return iterator}
The correct method of use is as follows:
Type yourtype struct {Name string}func exampleiterator () {set: = Newsetfromslice ([]interface{}{&yourtype{name: " Alise "},&yourtype{name:" Bob "},&yourtype{name:" John "},&yourtype{name:" Nick "},}) var found *yourtypeit: = set. Iterator () for elem: = range it. C {if elem. (*yourtype). Name = = "John" {found = Elem. (*yourtype) it. Stop ()}}fmt. Printf ("Found%+v\n", Found)//Output:found &{name:john}}
There is another way, as follows:
Func (set *threadsafeset) Iter () <-chan interface{} {ch: = Make (chan interface{}) go func () {set. Rlock () for elem: = range SET.S {ch <-elem}close (CH) set. Runlock ()} () return ch}
This method must traverse through all the elem elements, otherwise it will cause Gorountine to block. So must not break within the loop.
2. Understanding Chan Chan types
A small demo helps to understand the code as follows:
Import ("Time" "FMT") func main () {//Make the request Chan Chan this both go-routines would be givenrequestchan: = Make (chan Chan string)//Start the Goroutinesgo Goroutinec (Requestchan) go goroutined (Requestchan)//sleep for a second-let the G Oroutines Completetime. Sleep (time. Second)}func Goroutinec (Requestchan Chan Chan string) {//Make a new response Chanresponsechan: = Make (Chan string)//Send The Responsechan to Goroutinedrequestchan <-responsechan//Read the Responseresponse: = <-responsechanfmt.printf ( "Response:%v\n", Response)}func goroutined (Requestchan Chan Chan string) {//Read the Responsechan from the Requestchanre Sponsechan: = <-requestchan//Send a value down the Responsechanresponsechan <-"wassup!"}
Chan Chan types have great uses, such as the processing of millions of traffic per minute.
Reference:
(1) http://tleyden.github.io/blog/2013/11/23/understanding-chan-chans-in-go/
(2) https://www.goin5minutes.com/blog/channel_over_channel/
(3) http://marcio.io/2015/07/handling-1-million-requests-per-minute-with-golang/