Golang Accumulation-memory closure

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

In the Go language, functions as a class type can be passed and used as values. Closures, however, are the combination of function and environment variables. function as a parameter, using the characteristics of closures, you can use concise code to provide practical functions.
It was previously mentioned that call was combined with a WG to avoid the same time-consuming operation that caused the system to crash. "Golang accumulates-call callback mode", which is used in Groupcache "GitHub" code for the same data during lazy loading, the database overheating request. For specific code see: "Singleflight.go".
But if it's not an access violation at the same time, it's a one-by-one repeat process, and we usually take the cache into account in order to avoid repeated computations, especially time-consuming and general-purpose computational processing and database queries. Usually very kind of code similar in many places:

cache:=make(map[string]interface{})//...if _,founded:=cache[key];founded{//do something}else{v:=function(key)cache[key]=v}

If you are using more scenarios in your business, consider encapsulating them in higher-order functions and encapsulating the cache within the function to filter them.

The basic form of the Memcache function

//functions that need to be cache resultstypeMemoizefunctionfunc(int, ...int)int//encapsulates the cache's high-order function, and each operation looks for the cache first, and if not, computesfuncMemoize (function Memoizefunction) memoizefunction{//Encapsulated Cachecache:= Make(Map[string]int)return func(xintXs...int)int{///1, the input parameters of the function are expanded and merged into a string, as the key of the cache. This is useful for parameters in order. Key:=fmt. Sprint (x) for_,i:=Rangexs{key+=fmt. Sprintf (",%d", i)}//2, find in cache        ifvalue,found:=cache[key];found{returnValue}///3, no cache, then calculate, and the result into the cacheValue:=function (X,xs ...) Cache[key]=valuereturnValue}}//Specific business methods very time-consuming calculationsvarCaculate = Memoize (func(xintXs...int)int{//1 seconds of internal processing via sleep simulationTime. Sleep (time. Second)//Randomly returns a result    returnRand. Intn(Ten)})funcMain () {//Simulation calculation 100 times, actually only the first 10 times is real calculation, behind will cache results.      forI: =0; I < -; i++ {caculate (i%Ten)    }}

In the code, the function of memoize is actually similar to the result pool. You only need to modify the specific code inside Caculate at a time. Whether it has been cache or recalculated has been encapsulated by Memoize. For this part of the code, it can be understood as:

    1. The memoize is a separate operating area,
    2. Caculate The return value of memoize to access only the cache that is visible to it, it is clear that the 19th line of code can be converted to an anonymous function:
//...//3、没有缓存,则计算,并将结果那入到cache中        value:=func(x,xs...int)int{//<------此处开始,用匿名函数展开caculate的函数代码        time.Sleep(time.Second)        return rand.Intn(10)        }(x,xs...)        cache[key]=value       //<--------对匿名函数而言,cache是外部公用的        return value

Extension of the Memcache function

In reality, there are several drawbacks to the preceding code:
1. The return value is cosmetic and is limited in size.
2. The input value is shaped and is not suitable for other forms.
Due to the syntax characteristics of Go, the return value can be changed to interface{}, and then converted according to the specific business. The input value is converted as appropriate.
In some data, the use of cache to circumvent multiple recursion is referred to in the calculation optimization of Fibonacci functions. The code is as follows:

 PackageMainImport "FMT"//Extend the result form to interface{}typeMemoizefunctionfunc(int, ...int)Interface{}varFibonacci memoizefunctionfuncInit () {Fibonacci = Memoize (func(xintXs...int)Interface{} {ifX <2{returnX}returnFibonacci (x-1). (int) + Fibonacci (x-2). (int)    })}funcMemoize (function Memoizefunction) memoizefunction {//Encapsulated CacheCache: = Make(Map[string]Interface{})return func(xintXs...int)Interface{} {key: = FMT. Sprint (x) for_, I: =Rangexs {key + = FMT. Sprintf (",%d", i)}ifValue, found: = Cache[key]; Found {returnValue}//No cache, then calculate, and the result into the cacheValue: = function (x, xs ...) Cache[key] = valuereturnValue}}funcMain () {FMT. Println ("Fibonacci () =", Fibonacci())}

At this point, because of recursion, the feeling will be more complicated. The principle has not changed,

    1. The cache in Memoize is created when the Fibonacci is initialized, which is when the following line of code appears:

      Fibonacci = Memoize (func (x int, xs ... int) interface{} {

    2. Fibonacci recursion, just from key: = Fmt. The Sprint (x) begins execution, which is communicated with the traditional recursive invocation.

Other

The key conversion in the code is, in fact, orderly.

key:=fmt.Sprint(x)for _,i:=range xs{    key+=fmt.Sprintf(",%d",i)}

If the incoming parameter is an unordered collection, and the order of the collection elements is different, the key is not the same at this point, and the result cannot be directly positioned, and will still be recalculated. Consider changing the incoming parameter to interface{} and sorting should be optimized.

The cache is private inside the function

In the same file, even if multiple functions use memoize, there is no need to worry about the same key conflict, because each function will have an internal cache, which is the feature of the closure function.

In short, by encapsulating the memory closure of the cache, combined with the call mode, the performance and robustness of the system will be greatly improved. In essence, it is the use of syntax to replace some patterns of application. Of course, from a code style, the individual thinks that Golang's memory closures are more difficult to understand than Scala's higher-order functions. This may be an exception!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.