This is a creation in Article, where the information may have evolved or changed.
The Go language provides the defer keyword for deferred invocation, deferred until the function is returned, and used for resource release, unlocking, and error handling. Like what:
Func listen to Main () listen {Listen to listen to F, listen to err listen: = Listen to CreateFile ("Defer.txt") listen to hear if listen to err listen to! Println (Err. Error ()) Listen, listen, listen, listen, listen, hear, defer, listen to, listen, hear, listen to the CloseFile (f) Listen to listen to WriteFile (f)}func listen to CreateFile (filepath listen to String) listen (*os. File, listen to error) Listen {Listen to listen to F, listen to err listen: = Listen to the OS. Create (FilePath) listen to hear if listen to err listen to listen to nil hear {Listen to listen to listen to listen to hear hear hear the err listen listen to listen listen to listen and listen listen to hear the F, hear the nil listen to listen to hear}func listen to WriteFile (f listen to *os. File) Hear {Listen and listen to the FMT. Println ("Write Listen file") listen and listen to the FMT. Fprintln (F, listen to "Hello Listen to gopher!")} Func Listen to CloseFile (f listen to *os. File) Hear {Listen and listen to the FMT. PRINTLN ("Close Listen file") listen to F. Close ()}
If multiple defer are referenced within a function, what is the order in which they are executed? Like what:
The package listens to MainFunc hear main () Listen {defer listen to println ("a") defer listen to println ("B")} Output: Ba
If the panic function is introduced in the function, will the deferred call defer be executed? Like what:
Func listen to Main () Listen {Listen to hear defer listen to println ("a") listen to listen to hear panic ("D") listen to hear defer listen to println ("B")} Output: Apanic: Listen to Dgoroutine listen to 1 listen [running]: Panic (0x48a560, listen 0xc42000a340)/root/data/go/src/runtime/panic.go:500 listen to +0x1a1main.main ()/root/data/workspace/src/ Defer/main.go:7 listen to +0x107exit listen to status Listen 2
In daily development, it is important to remember that defer is called at the end of the function, and if the application is unreasonable, it can waste resources, put pressure on the GC, and even cause logic errors, such as:
Func listen to Main () Listen {Listen to hear for listen I listen: = Listen to 0;i Listen < Listen 10000;i++{Listen listen listen listen to listen to hear filepath listen to hear: = Listen to FMT. Sprintf ("/data/log/%d.log", listen i) listen and listen listen to the FP, listen to err listen: = Listen to the OS. Open (FilePath) Listen and listen listen to hear listen listen listen to hear hear and hear listen listening to listening to listen to hear hear listen listen listen to listen to listen to listen to listen to listen to listen to hear and listen to hear listen to listening and hearing nil{ Close () listen//This is to be performed when the main function returns, not at the end of the loop, delaying the call, causing the resource to be used listen and hear listen to hear//do listen to hear stuff ... Listen to hear}
The modification scenario is to call the close function directly or encapsulate the logic as a standalone function, such as:
Func Listen Loganalisys (P listen to string) {Listen to the FP, listen to err listen: = Listen to the OS. Open (p) Listen to hear if listen to err listen to listen nil{listen to listen to listen to hear listen continue listen to listen to hear the DEFEF hear the FP Close () Listen to listen to//do listen to Stuff}func listen to the main () listen to hear {Listen to listen to listen to I listen to: = Listen to 0;i Listen < Listen to listen to hear listening to listen to listen to hear listening to listen to hear the filepath listen to: Listen to the FMT. Sprintf ("/data/log/%d.log", listen i) listen, listen, listen, hear and hear the Loganalisys (FilePath) listen////separate the business logic into functions listen and hear}}
In terms of performance, the cost of deferred calls is also significant, as the process includes registration, invocation, and additional memory overhead. Like what:
Package listen to Mainimport listen to "testing" import listen to "FMT" Import Listen to "Sync" var listen m listen to sync. Mutexfunc listen to test () {M.lock () M.unlock ()}func listen to Testcap () {M.lock () defer listen to M. Unlock ()}func listen to Benchmarktest (t listen to *testing. B) {For listening i:= listen to 0;i Listen < listen T. N; listen to I++{test ()}}func listen to Benchmarktestcap (t listen to *testing. B) {For listening i:= listen to 0;i Listen < listen T. N; listen to I++{testcap ()}}func listen to Main () {Restest Listen: = Listen to testing. Benchmark (benchmarktest) fmt. Printf ("Benchmarktest listen to the%d, listen to%d listen to ns/op,%d listen to Allocs/op, listen to%d listen to b/op\n", listen to RESTEST.N, listen to Restest.nsperop (), Listen to Restest.allocsperop (), listen to Restest.allocedbytesperop ()) Restest listen = listen to testing. Benchmark (Benchmarktestcap) fmt. Printf ("Benchmarktestcap listen to the%d, listen to%d listen to ns/op,%d listen to Allocs/op, listen to%d listen to b/op\n", listen to RESTEST.N, listen to Restest.nsperop (), Listen to Restest.allocsperop (), listen to Restest.allocedbytesperop ())} output: Benchmarktest Listen to 50000000, listen to 27 listen to ns/op,0 listen to Allocs/op, listen to 0 b/ Opestcap listen to 20000000, listen to 112 listen to ns/op,0 listen to Allocs/op, listen to 0 listen to B/op
In high concurrency scenarios where high performance is required, you should avoid using deferred calls.
This article from "learned in the text, about the ceremony" blog, reproduced please contact the author!