方法一:

1, 首先介绍一下 “sync/atomic” 包下面的SwapInt32 函数

用法:

func SwapInt32(addr *int32, new int32) (old int32)

解释:函数用于将新值自动存储到* addr中,并返回先前的* addr值。原子操作

返回值:它将新的int32值存储到* addr中,并返回先前的* addr值。

2, 举例 如何实现流量控制

func main() { 
 
    var precent int32 = 0 

    loop := 0
    
    // 截取10%的流量
    rate := 10 
    
    for {
        i ++;
        if loop > 1000 {
            break;
        }
        var old_val = atomic.SwapInt32(&precent, (precent+1)%100) 
        if old_val < 10 {
           fmt.Println(" capture the traffic", old_val) 
        }
        // Prints new and old value 
        fmt.Println("Stored new value:", precent, ", Old value:", old_val) 
    }
    
}

方法二:

1,首先介绍一下 “sync/atomic” 包下面的AddUint32() 函数

func AddUint32(addr *uint32, delta uint32) (new uint32)

addr表示地址,而delta表示少量大于零的位

方法解释:原子的把将增量自动添加到* addr中并返回改地址上新的值

返回值:它自动添加addr和delta并返回一个新值。

例如:如果我们要原子的将int32类型的变量i32的值减小3话,可以这样操作:atomic.AddInt32(&i32, -3)

2,实现一个流量控制类。

第一步,定义流量控制类

type TrafficCapture struct {
    // 存放流量数据
	source     []int

	queryCount uint32

	// the capture base num,for example 100
	base       int

	// the captrue rate 
	ratio      int
  }

第二部:初始化控制类

func NewTrafficCapture(base int, ratio int) *TrafficCapture {

	source := make([]int, base)

	for i := 0; i < base; i++ {
	  source[i] = i
	}

	// 打乱数据
	rand.Shuffle(base, func(i, j int) {
	  source[i], source[j] = source[j], source[i]
	})


	return &TrafficControl{
	  source: source,
	  base:   base,
	  ratio:  ratio,
	}
  }

第三部分:流量截取

返回true,则截取流量,返回false则放过

func (t *TrafficControl) Allow() bool {
	
	rate := t.source[int(atomic.AddUint32(&t.queryCount, 1))%t.base]
	if rate < t.ratio {
	  return true
	} else {
	  return false
	}
  }