go chan实践

353 阅读1分钟
  • 定义结构体

    type RestChan struct {
    	Status uint32   //true为已关闭
    	Rw sync.RWMutex  
    	Ch chan *azmode.ResultMode
    	Wg sync.WaitGroup
    }

  • 构造new方法

    func NewRestChan(len int16) *RestChan  {
    	var ch chan *azmode.ResultMode
    	ch = make(chan *azmode.ResultMode, len)
    	return &RestChan{Ch:ch}
    }

  • 结构体方法get

    //从chan获取数据
    func (r *RestChan)Get()(bool, *azmode.ResultMode)  {
    	var(
    		ok bool
    		rest *azmode.ResultMode
    	)
    	select {
    	case rest, ok = <- r.Ch:
    		if !ok{
    			fmt.Println("***********RestChan 已关闭")
    			return false, nil
    		}
    	case <-time.After(time.Second*1):
    		return false, nil
    	//default:
    	//	//fmt.Println("***********RestChan 中暂时没有数据")
    	//	return false, nil
    	}
    
    	return true, rest
    }

  • 结构体方法put

    //向chan发送数据
    func (r *RestChan)put(rest *azmode.ResultMode) bool  {
    
    	select {
    	case r.Ch <- rest:
    		return true
    	default:
    		//fmt.Println("***********RestChan 已满")
    		return false
    	}
    }

  • 结构体方法close

    //关闭chan
    func (r *RestChan)Close()  {
    	var(
    		state uint32
    	)
    	r.Rw.Lock()
    	state = atomic.LoadUint32(&r.Status)
            //判断chan是否已为关闭状态
    	if state!=1{
    		if atomic.CompareAndSwapUint32(&r.Status, state, 1){
    			fmt.Println("***********开始关闭RestChan")
    			close(r.Ch)
    		}
    	}
    	defer r.Rw.Unlock()
    }

  • 实践数据发送到chan

    //持续发送数据到restChan,直到LT24SChan关闭
    func (r *RestChan)PushSRest()  {
    	var(
    		bl bool
    		rest *azmode.ResultMode
    	)
    	for{
    		if bl, rest = LT24SChan.Get(); !bl{
                            //判断chan是否关闭
    			if atomic.LoadUint32(&LT24SChan.Status) != 1{
    				//fmt.Println("**************LT24SChan 暂时没有数据")
    				continue
    			}
    			fmt.Println("*****************已关闭 LT24SChan.Ch ")
    			break
    
    		}else {
    			if rest !=nil{
    				//发送数据到RestChan
    				if bl = RestCh.put(rest); !bl{
    					//异步发送,同步会造成阻塞在这里
    					r.Wg.Add(1)
    					go func(rest *azmode.ResultMode) {
    						var bl bool
    						for{
    							if bl = RestCh.put(rest); !bl{
    								continue
    							}
    							break
    						}
    						defer r.Wg.Done()
    					}(rest)
    				}
    			}
    			//fmt.Println("key 已存在")
    			continue
    		}
    	}
    }

  • 实践关闭chan

    go func() {
    		//确定所有向chan发送的数据已经完成
    		chanpip.RestCh.Wg.Wait()
    		chanpip.RestCh.Close()
    	}()