// Backoff returns the amount of time to wait before the next retry given the // number of retries. // 根据retries返回等待时间,可以认为是一种退避策略 func(bc Exponential)Backoff(retries int)time.Duration { if retries == 0 { // 之前没有retries过,就返回BaseDelay return bc.Config.BaseDelay } backoff, max := float64(bc.Config.BaseDelay), float64(bc.Config.MaxDelay) // 等待时间不能超过max,等待时间 = BaseDelay * Multiplier的retries次方 // Multiplier默认1.6,并不是官方http包中的2 for backoff < max && retries > 0 { backoff *= bc.Config.Multiplier retries-- } if backoff > max { backoff = max } // Randomize backoff delays so that if a cluster of requests start at // the same time, they won't operate in lockstep. // 乘以一个随机因子,数值为(1-Jitter,1+Jitter),默认为(0.8,1.2),防止同一时刻有大量请求发出,引起锁的问题 backoff *= 1 + bc.Config.Jitter*(grpcrand.Float64()*2-1) if backoff < 0 { return0 } return time.Duration(backoff) }
type HttpHandlerDecorator func(http.HandlerFunc)http.HandlerFunc funcHandler(h http.HandlerFunc, decors ...HttpHandlerDecorator)http.HandlerFunc { for i := range decors { d := decors[len(decors)-1-i] // iterate in reverse h = d(h) } return h }
funcTransformInPlace(slice, function interface{})interface{} { return transform(slice, function, true) }
// map的转换函数,slice为切片,function为对应的函数,inPlace表示是否原地处理 functransform(slice, function interface{}, inPlace bool)interface{} { // 类型判断,必须为切片 sliceInType := reflect.ValueOf(slice) if sliceInType.Kind() != reflect.Slice { panic("transform: not slice") }
// 函数的签名判断,即函数的入参必须和slice里的元素一致 fn := reflect.ValueOf(function) elemType := sliceInType.Type().Elem() if !verifyFuncSignature(fn, elemType, nil) { panic("trasform: function must be of type func(" + sliceInType.Type().Elem().String() + ") outputElemType") }
// 如果是原地,则直接处理函数,结果会保存到入参中(这时入参一般为指针) // 如果非原地,那就需要新建一个切片,用来保存结果 sliceOutType := sliceInType if !inPlace { sliceOutType = reflect.MakeSlice(reflect.SliceOf(fn.Type().Out(0)), sliceInType.Len(), sliceInType.Len()) } for i := 0; i < sliceInType.Len(); i++ { sliceOutType.Index(i).Set(fn.Call([]reflect.Value{sliceInType.Index(i)})[0]) } return sliceOutType.Interface()