search
HomeBackend DevelopmentGolangAn article explains in detail the implementation principle of golang defer

This article is introduced by the go language tutorial column to introduce the implementation principle of golang defer. I hope it will be helpful to friends in need!

defer is a keyword provided by golang, which is called after the function or method completes execution and returns.
Each defer will push the defer function into the stack. When the function or method is called, it will be taken out from the stack for execution. Therefore, the execution order of multiple defers is first in, last out.

for i := 0; i <p><strong>defer trigger timing</strong></p><p>The official website makes it very clear:<br>A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function returns, either because the surrounding function executed a return statement, reached the end of its function body, or because the corresponding goroutine is panicking.</p><ol>
<li>When the function wrapped in the defer statement returns</li>
<li>When the function wrapped in the defer statement is executed to the end</li>
<li>
<p>When the current goroutine panics</p>
<pre class="brush:php;toolbar:false">    //输出结果:return前执行defer
   func f1() {
       defer fmt.Println("return前执行defer")
       return 
   }

   //输出结果:函数执行
   // 函数执行到最后
   func f2() {
       defer fmt.Println("函数执行到最后")
       fmt.Println("函数执行")
   }

   //输出结果:panic前  第一个defer在Panic发生时执行,第二个defer在Panic之后声明,不能执行到
   func f3() {
       defer fmt.Println("panic前")
       panic("panic中")
       defer fmt.Println("panic后")
   }

defer, return, return value execution order

Let’s look at 3 examples first

func f1() int { //匿名返回值
        var r int = 6
        defer func() {
                r *= 7
        }()
        return r
}

func f2() (r int) { //有名返回值
        defer func() {
                r *= 7
        }()
        return 6
}

func f3() (r int) { //有名返回值
    defer func(r int) {
        r *= 7
    }(r)
    return 6
}

The execution result of f1 is 6, the execution result of f2 is 42, the execution result of f3 is 6
In the official document of golang It introduces the execution order of return, defer, and return value:
if the surrounding function returns through an explicit return statement, deferred functions are executed after any result parameters are set by that return statement but before the function returns to its caller .

1. Assign the return value first
2. Execute the defer statement
3. Wrap the function return to return

The result of f1 is 6. f1 is an anonymous return value. The anonymous return value is declared when return is executed. Therefore, when defer is declared, the anonymous return value cannot be accessed. Modification of defer will not affect the return value.
f2 first assigns the return value r, r=6, executes the defer statement, defer modifies r, r = 42, and then the function returns.
f3 is a named return value, but because r is used as a parameter of defer, when declaring defer, the parameters are copied and passed, so defer will only affect the local parameters of the defer function and will not affect the calling function. The return value.

Closures and anonymous functions
Anonymous function: A function without a function name.
Closure: A function that can use variables in the scope of another function.

for i := 0; i <p><strong>defer source code analysis</strong><br>The implementation source code of defer is in runtime.deferproc<br>Then run the function runtime.deferreturn before the function returns. <br>First understand the defer structure: </p><pre class="brush:php;toolbar:false">    type _defer struct {
            siz     int32 
            started bool
            sp      uintptr // sp at time of defer
            pc      uintptr
            fn      *funcval
            _panic  *_panic // panic that is running defer
            link    *_defer
    }

sp and pc point to the stack pointer and the caller's program counter respectively, fn is the function passed into the defer keyword, and Panic is the Panic that causes defer to be run. .
Every time a defer keyword is encountered, the defer function will be converted into runtime.deferproc
deferproc creates a delay function through newdefer, and hangs this new delay function on the current goroutine's _defer linked list

    func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn
            sp := getcallersp()
            argp := uintptr(unsafe.Pointer(&fn)) + unsafe.Sizeof(fn)
            callerpc := getcallerpc()

            d := newdefer(siz)
            if d._panic != nil {
                    throw("deferproc: d.panic != nil after newdefer")
            }
            d.fn = fn
            d.pc = callerpc
            d.sp = sp
            switch siz {
            case 0:
                    // Do nothing.
            case sys.PtrSize:
                    *(*uintptr)(deferArgs(d)) = *(*uintptr)(unsafe.Pointer(argp))
            default:
                    memmove(deferArgs(d), unsafe.Pointer(argp), uintptr(siz))
            }
            return0()
    }

newdefer will first take out a _defer structure from the deferpool of sched and current p. If the deferpool does not have _defer, a new _defer will be initialized.
_defer is associated with the current g, so defer is only valid for the current g.
d.link = gp._defer
gp._defer = d //Use a linked list to connect all defers of the current g

    func newdefer(siz int32) *_defer {
            var d *_defer
            sc := deferclass(uintptr(siz))
            gp := getg()
            if sc  0 {
                            d = pp.deferpool[sc][n-1]
                            pp.deferpool[sc][n-1] = nil
                            pp.deferpool[sc] = pp.deferpool[sc][:n-1]
                    }
            }
            ......
            d.siz = siz
            d.link = gp._defer
            gp._defer = d
            return d
    }

deferreturn Take out the _defer linked list from the current g and execute it, each _defer call freedefer releases the _defer structure and puts the _defer structure into the deferpool of the current p.

defer performance analysis
defer is very useful in development for releasing resources, capturing Panic, etc. It is possible that some developers have not considered the impact of defer on program performance and abuse defer in their programs.
It can be found in the performance test that defer still has some impact on performance. Yuchen's Go performance optimization tips 4/1, there are some tests on the extra overhead caused by defer statements.

Test code

    var mu sync.Mutex
    func noDeferLock() {
        mu.Lock()
        mu.Unlock()
    }   

    func deferLock() {
        mu.Lock()
        defer mu.Unlock()
    }          
    
    func BenchmarkNoDefer(b *testing.B) {
        for i := 0; i <p><strong>Test result:</strong></p><pre class="brush:php;toolbar:false">    BenchmarkNoDefer-4      100000000               11.1 ns/op
    BenchmarkDefer-4        36367237                33.1 ns/op

It can be known from the previous source code analysis that defer will first call deferproc , these will copy parameters, and deferreturn will also extract relevant information and delay execution. These are more expensive than directly calling a statement.

The performance of defer is not high. Each defer takes 20ns. If it occurs multiple times in a func, the performance consumption is 20ns*n. The cumulative waste of CPU resources is very large.

Solution: Except when exception capture is required, defer must be used; for other resource recycling defers, you can use goto to jump to the resource recycling code area after judging failure. For competitive resources, you can release the resources immediately after use, so that the competitive resources can be optimally used.

For more golang related knowledge, please visit the golangtutorial column!

The above is the detailed content of An article explains in detail the implementation principle of golang defer. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:segmentfault. If there is any infringement, please contact admin@php.cn delete
Golang vs. Python: The Pros and ConsGolang vs. Python: The Pros and ConsApr 21, 2025 am 12:17 AM

Golangisidealforbuildingscalablesystemsduetoitsefficiencyandconcurrency,whilePythonexcelsinquickscriptinganddataanalysisduetoitssimplicityandvastecosystem.Golang'sdesignencouragesclean,readablecodeanditsgoroutinesenableefficientconcurrentoperations,t

Golang and C  : Concurrency vs. Raw SpeedGolang and C : Concurrency vs. Raw SpeedApr 21, 2025 am 12:16 AM

Golang is better than C in concurrency, while C is better than Golang in raw speed. 1) Golang achieves efficient concurrency through goroutine and channel, which is suitable for handling a large number of concurrent tasks. 2)C Through compiler optimization and standard library, it provides high performance close to hardware, suitable for applications that require extreme optimization.

Why Use Golang? Benefits and Advantages ExplainedWhy Use Golang? Benefits and Advantages ExplainedApr 21, 2025 am 12:15 AM

Reasons for choosing Golang include: 1) high concurrency performance, 2) static type system, 3) garbage collection mechanism, 4) rich standard libraries and ecosystems, which make it an ideal choice for developing efficient and reliable software.

Golang vs. C  : Performance and Speed ComparisonGolang vs. C : Performance and Speed ComparisonApr 21, 2025 am 12:13 AM

Golang is suitable for rapid development and concurrent scenarios, and C is suitable for scenarios where extreme performance and low-level control are required. 1) Golang improves performance through garbage collection and concurrency mechanisms, and is suitable for high-concurrency Web service development. 2) C achieves the ultimate performance through manual memory management and compiler optimization, and is suitable for embedded system development.

Is Golang Faster Than C  ? Exploring the LimitsIs Golang Faster Than C ? Exploring the LimitsApr 20, 2025 am 12:19 AM

Golang performs better in compilation time and concurrent processing, while C has more advantages in running speed and memory management. 1.Golang has fast compilation speed and is suitable for rapid development. 2.C runs fast and is suitable for performance-critical applications. 3. Golang is simple and efficient in concurrent processing, suitable for concurrent programming. 4.C Manual memory management provides higher performance, but increases development complexity.

Golang: From Web Services to System ProgrammingGolang: From Web Services to System ProgrammingApr 20, 2025 am 12:18 AM

Golang's application in web services and system programming is mainly reflected in its simplicity, efficiency and concurrency. 1) In web services, Golang supports the creation of high-performance web applications and APIs through powerful HTTP libraries and concurrent processing capabilities. 2) In system programming, Golang uses features close to hardware and compatibility with C language to be suitable for operating system development and embedded systems.

Golang vs. C  : Benchmarks and Real-World PerformanceGolang vs. C : Benchmarks and Real-World PerformanceApr 20, 2025 am 12:18 AM

Golang and C have their own advantages and disadvantages in performance comparison: 1. Golang is suitable for high concurrency and rapid development, but garbage collection may affect performance; 2.C provides higher performance and hardware control, but has high development complexity. When making a choice, you need to consider project requirements and team skills in a comprehensive way.

Golang vs. Python: A Comparative AnalysisGolang vs. Python: A Comparative AnalysisApr 20, 2025 am 12:17 AM

Golang is suitable for high-performance and concurrent programming scenarios, while Python is suitable for rapid development and data processing. 1.Golang emphasizes simplicity and efficiency, and is suitable for back-end services and microservices. 2. Python is known for its concise syntax and rich libraries, suitable for data science and machine learning.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

SecLists

SecLists

SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

DVWA

DVWA

Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.