Fundamentals 15 min read

Understanding Go Function Pointers and Their Performance Impact

The article explains how Go’s function values introduce an extra indirection and trigger escape analysis, making indirect calls slower than C pointers, and offers optimization tactics such as avoiding function‑pointer calls, using switch‑based dispatch, or applying the unsafe noescape trick when safe.

Tencent Cloud Developer
Tencent Cloud Developer
Tencent Cloud Developer
Understanding Go Function Pointers and Their Performance Impact

This article examines the performance implications of Go's function values (often called "function pointers") and provides concrete optimization strategies based on assembly inspection.

Background

When micro‑optimising Go code, developers notice that function calls are slower than in C/C++ and that the penalty grows when pointer arguments are involved. The article analyses why and how to mitigate the overhead.

1. Function call implementation in C

Example C code:

int Add(int a, int b) { return a + b; }

Generated assembly (x86‑64, Linux):

Add:
lea    eax, [rdi+rsi]
ret

According to the calling convention, the first two integer arguments are passed in RDI and RSI , and the result is returned in EAX .

2. Function call implementation in Go

Simple Go function:

func Add(a, b int) int { return a + b }

Generated assembly (Go 1.17+, x86‑64):

main.Add STEXT nosplit size=4 args=0x10 locals=0x0 funcid=0x0 align=0x0
0x0000 00000 (
:4) ADDQ BX, AX
0x0003 00003 (
:4) RET

The registers differ ( AX , BX ) but the overall cost is similar.

3. Returning a function value

Go code that returns a closure:

func MakeAdd() func(int, int) int { return func(a, b int) int { return a + b } }

Generated assembly:

main.MakeAdd STEXT nosplit size=8 args=0x0 locals=0x0 funcid=0x0 align=0x0
0x0000 00000 (
:15) LEAQ main.Add·f(SB), AX
0x0007 00007 (
:15) RET

The function value does not point directly to the code; it points to a small data object ( ·f ) that contains the real address.

4. Indirect call via a function pointer

Calling a function through a pointer:

func CallAddPtr(add func(int, int)) { add(1, 2) }

Generated assembly (simplified):

main.CallAddPtr STEXT nosplit size=51 args=0x8 locals=0x18 funcid=0x0 align=0x0
...
MOVQ (DX), CX          // load the real function address
CALL CX                // indirect call

Compared with the direct call, an extra memory load is required, and the compiler can no longer prove that the argument does not escape.

5. Escape analysis impact

When a variable is passed to a function pointer, the compiler conservatively assumes the address may be stored for later use, causing the variable to escape to the heap. Example:

func CallSetPtr(set func(*int)) { a := 0; set(&a) }

Generated assembly shows a heap allocation via runtime.newobject before the indirect call, confirming the escape.

Escape analysis can be inspected with the -m flag, and the performance penalty of heap allocation is often larger than the extra instruction overhead.

6. Mitigating escape with noescape

Go's runtime provides a helper that hides a pointer from escape analysis:

//go:nosplit
func noescape(p unsafe.Pointer) unsafe.Pointer {
    x := uintptr(p)
    return unsafe.Pointer(x ^ 0)
}

By applying a trivial XOR, the compiler treats the result as unrelated to the original pointer, preventing escape. This must be used with care to ensure the pointer is not stored for later use.

7. Switch‑based dispatch

If the set of possible function pointers is small, a switch statement can replace indirect calls, eliminating the extra load and escape. The Go time package uses this technique for formatting.

Conclusion

Go's function‑value implementation adds an extra level of indirection and can trigger escape analysis, making it slower than equivalent C function pointers. For most code, readability should dominate, but when micro‑optimising, consider avoiding indirect calls, using switch dispatch, or the noescape trick where safe.

PerformanceoptimizationcompilerGoEscape Analysisfunction pointers
Tencent Cloud Developer
Written by

Tencent Cloud Developer

Official Tencent Cloud community account that brings together developers, shares practical tech insights, and fosters an influential tech exchange community.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.