Go language fully resolved Go! Go! Go! Function (a) type of data

1, with the closure anonymous functions

Closures are anonymous functions and anonymous functions referenced by the environment portfolio , namely closure + = anonymous function references environment, specifically, how to understand it? Start example start

Example. 1: 
FUNC Squares () FUNC () int {     // Squares return value is a function of the type of a variable, the function type is FUNC () int 
    var X int 
    return FUNC () int {// create an anonymous internal function function, the function as the return value to the upper 
        X ++
         return X * X 
    } 
} 

F: = squares () // perform squares function to get a function body 
fmt.Println (F ())
// performed to create squares function, the result is obtained ". 1"
fmt.Println (F ()) // performed again to give the result ". 4"
fmt.Println (F ()) // ". 9"
fmt.Println (F ())
// " 16 "

 Small Summary: The above way is closure technology (closures), you first need to create an anonymous function, then the anonymous function references a variable outer function of x (namely reference environment)

 

var funcArray [] func ()
for I: = 0; I <. 3; I ++ {for I: = 0; I <. 3; I ++ { 
                                                                 J: = I       // J is defined in the circulation 
    funcArray = append (funcArray, func { print (i)} ) = funcArray the append (funcArray, FUNC {Print (I)})      
}} 
funcArray [0] () // result: 3 @ results:. 1
funcArray [. 1] () // result: 3 @ results: 2
funcArray [2] () // result: 3 @ results: 3

small Summary: a first, closure referenced environment variable is a function of i layer, after executing the loop, the variable i is 3, then again closure is performed, the result is 3
second,
closure reference of the environment variable j outer function, different closures are obtained different j (j is as defined in the cycle).
Note that if j is defined outside the loop, then the loop is j = i, then the end result is 222, think about why? 

summary:

Closures What are the benefits? What is the scenario?

a, by the closure of the local variables inside a function exposed

b, the memory effect closure: closure of logic can modify variables closure captured variables will follow the closure lifetime has always existed, the closure itself like other variables have a memory effect, this time as a global variable there is general variables.

c, so that the value of certain variables remain in memory as long as the closure is still quoted, would not be called after the end of the outer function, variable been garbage collection (garbage collection).

 

 

2, the variable parameters of the function sections and

func sum(vals ...int) int{
total := 0
for _, val := range vals{
   total += val
}
return total
}
SUM () 
SUM (
. 3 )
SUM (
. 1 , 2 , . 3 , . 4 )

var values [] int { 10 , 20 is , 30 }
SUM (values ...)

Small Summary: ... Type: can be seen as a complex type, type indicates a slice type (including the bottom of the array), after coming into the reference pile, copies these parameters to the array, can then be accessed using a traversing manner
variables ...: first variable must be some slice type (of course, must have an array corresponding to the bottom), and a plurality of variable parameters says ..., each parameter value is an array
i.e., variable type and ... ... in two forms, official one pair!

 

2, defer use (closures + defer)

        FUNC Double (X int ) (Result int ) { 
0) zero mode: the defer
fmt.Println ( "the defer:", X) is the defer // a statement is not a function (closure)
1) Method 1: defer func ( ) {result + x} = () // first closure configuration (x references the environment and result), also cited in the closure function of the result before the result and the environment by adding x
2) Second way: FUNC the defer (I int ) = {Result + I} (X) // closure cited only environment variables result, after the same reference function (so to define with the closure in the closure member (the reference closure) the format calls)
the X- ++ return the X-      }       
      

0) double (10) // 10 results. To defer in the implementation, the statement stack, at this time has a fixed value of x 
1) double (10) // 22 results. When the return, the value of x is 11, the value of x is equal Result 11, after closure performed again became 22 is
2) Double (10) // 21. The result in the implementation of the statement to defer, closure loaded, this time into the reference value of i has been determined, i.e., the outer layer x (10), the time of return, i is 10, result is 11, the result is the implementation of the closure 21
Small Summary: return not an atomic instruction, including value assigned to return value ret 2 and true steps (statement / closures) defer the execution contents are placed between the two 
functions are referred to defer defered function, the whole the implementation of the principle is:
1) according to defer keywords will defered function onto the stack, if there are multiple defer statement, then turn recursion stack
2) wait until execution time to return statement, defered function turn the stack, perform
3) on the the reference value is determined when the stack is already
4) If the closure introduced external variables, with the general principle of closure
    is defer the sentence the same way, but if you reference a variable, the value pushed is the current value

 

2, panic and recover

Class, when the program panic anomaly, the program will be interrupted, and immediately execute the contents of the gouroutine (main location is also a goroutine) was defered, that turn the stack

                   Then, the system gives the crash log information, including panic value and the stack trace;

With recover, he will recover function does not continue, but returned to normal, but this is still a whole goroutine

func f(x int){
    defer func(){
        if recover() != nil{fmt.Println("before exec defer:recover after panic")}
    }()    
    fmt.Printf("f(%d)\n", x + 0/x)
    f(x-1)
}

func PrintStack()  {
    var buf [4096]byte
    n := runtime.Stack(buf[:],false)   //为什么一定要buf[:]
    os.Stdout.Write(buf[:n])
}

执行:
defer PrintStack()  
f(1 )    

Results:
F (1)

goroutine 1 [running]: ## This error message is cook PrintStack () function to print information on the stack information =
main.PrintStack () ## according to the current printing can know this, when the panic when the stack is in before defered function that is PrintStack function only after that the panic function,
  C: /Users/HX/go/src/myWork/testFunction.go: 54 + 0x62 
panic (0x4a6ba0, 0x533490) ## I was panic function, panic function following positive is about to cause panic in the statement
  C: /go1.10/src/runtime/panic.go: 505 + 0x237
main.f (0x0)
  C: /Users/HX/go/src/myWork/testFunction.go: 48 + 0xDE ## Yes, I'm really caused panic in the statement
main.f (0x1)
  C: /Users/HX/go/src/myWork/testFunction.go: 49 + 0xCF
main.testFunction ()
  C: / the Users / HX + 0x4D /go/src/myWork/testFunction.go:60
main.main ()
  C: /Users/HX/go/src/myWork/main.go: + 0x29. 4

-------------------------------------------------- ----------
panic: Runtime error: Integer Divide by ZERO # this error = error reason to cook your system directly quoted (panic value) + stack information

. 1 goroutines [running]:
main.f (0x0)
  C: /Users/go/src/myWork/testFunction.go: # 48 + 0xDE this line is performed 0/0 of that of Yang, so wrong, so the At present, all contents of the print is still stack up, here is the top of the stack
main.f (0x1)
  C: /Users/go/src/myWork/testFunction.go: 49 + 0xCF
main.testFunction ()
  C: / the Users / Go + 0x4D /src/myWork/testFunction.go:60
main.main ()
  C: /Users/go/src/myWork/main.go: + 0x29. 4

Process finished with exit code 2

 

====== If there recover operation, only the () function prints a stack information PrintStack, panic will not ======================== ===========================================

 

F (. 1)
before the defer Exec: After panic # recover the recover operation performed
goroutines. 1 [running]:
main.PrintStack ()
C: /Users/go/src/myWork/testFunction.go: 0x62 + # 54 is here print itself the statement that PrintStack print statements
main.testFunction ()
C: /Users/go/src/myWork/testFunction.go: 75 + 0x4e
main.main ()
C: /Users/go/src/myWork/main.go : 4 + 0x29
the Hello Go, the I Remember you Also shown here hahah # normal program execution continues, and has come to the end!!
Process Finished with Exit code 0

 

 

summary:

//runtime/runtime2.go
type _panic struct {
    // 调用defer时入参的指针
    argp unsafe.Pointer // pointer to arguments of deferred call run during panic; cannot move - known to liblink
    arg interface{} // argument to panic
    link *_panic // link to earlier panic
    recovered bool // whether this panic is over
    aborted bool // the panic was aborted
}

 

// Runtime / panic.go 
FUNC gopanic (E interface {}) { 
    GP: = getG () 
    ... 
    // initialize panic 
    var P _panic
     ... 

    // traverse the linked list of G defer 
    for { 
        D: = gp._defer 
        ... // call the function behind defer. If the function contains recover, it will call gorecover 
        reflectcall (nil, unsafe .Pointer (d.fn), deferArgs (d), uint32 (d.siz), uint32 (d.siz)) 
       ... // already recover the called 
        IF p.recovered { 
            MCALL (Recovery)
             the throw ( "recovery failed") // mcall should not return
        }
    }

    // 终止程序
    fatalpanic(gp._panic) // should not return
    *(*int)(nil) = 0      // not reached
}

1, we must first clear that runtime helping us run the program go there running, then program execution anomaly, we will call the panic function for run-time, run-time function to the corresponding level is gopanic

           Of course, we can call panic directly in the user program level, the same effect

2, then you can see, when panic function is executed, it will defer to traverse the list of G, then go to defer the implementation of function before abnormal exit, which is why PrintStack function to be executed, and at this moment there are defered stack function Information

3. Add recover, is to defer use of the principle, that will go to the following recover before exiting, so it is able to recover the following stack processing, so that the current goroutine not abnormal exit, specifically, the current sub-function of the normal return

          

 

 

 

 

 

 

 

 

Guess you like

Origin www.cnblogs.com/shuiguizi/p/11380635.html
Go