Hello, I'm Ganesh Kumar. I'm working on git-lrc: a Git hook for Checking AI generated code.AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.
In my previous post, I explained about how slices work internally in Go.
Also we found capacity of the slice is not always equal to the length of the slice after appending.
Now let's see why this happens and what is the reason behind it.
Appending to a slice
In the official source code of append function you can see here link
There are two cases for appending to a slice.
- Appending single element to a slice.
- Appending multiple elements to a slice.
Append single element to a slice:
package main
import "fmt"
func main() {
a := []int{}
printSlice(a)
a = append(a, 0)
printSlice(a)
a = append(a, 1)
printSlice(a)
a = append(a, 2)
printSlice(a)
a = append(a, 3)
printSlice(a)
a = append(a, 4)
printSlice(a)
a = append(a, 5)
printSlice(a)
a = append(a, 6)
printSlice(a)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
This will output:
gk@jarvis:~/exp/code/rd/go-exmaple$ go run main.go
len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=3 cap=4 [0 1 2]
len=4 cap=4 [0 1 2 3]
len=5 cap=8 [0 1 2 3 4]
len=6 cap=8 [0 1 2 3 4 5]
len=7 cap=8 [0 1 2 3 4 5 6]
We can see clearly on how the capacity is growing.
Whenever there is match with len and cap the next element will be appended with cap double the previous cap.
Internal Algorithm of Append Function
package main
import "fmt"
func main() {
a := []int{1, 2,}
printSlice(a)
a = append(a, 3)
printSlice(a)
a = append(a, 4,5,6,7,8,9)
printSlice(a)
a = append(a, 10,11,12)
printSlice(a)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
Output:
gk@jarvis:~/exp/code/rd/go-exmaple$ go run main.go
len=2 cap=2 [1 2]
len=3 cap=4 [1 2 3]
len=9 cap=10 [1 2 3 4 5 6 7 8 9]
len=12 cap=20 [1 2 3 4 5 6 7 8 9 10 11 12]
Append 1: Bulk append of 1,2
Inserted length is 2
Capacity is 2
Append 2: Single append of 3
Inserted length is 1
Capacity is 4
Which is double the previous capacity
Append 3: Bulk append of 4,5,6,7,8,9
Inserted length is 6
Capacity is 10
Which is double the previous capacity but increased by 2 to round off to bucket size
Append 4: Bulk append of 10,11,12
Inserted length is 3
Capacity is 20
Which is double the previous capacity
The underlying reasons for this behavior are:
- Safety Checks
- Zero-Size Shortcut: If the slice is empty, it skips allocation if possible.
-
Calculating the Target Capacity:
- If the current capacity is small (less than 256 elements), it will double the capacity.
- If the current capacity is large (256 elements or more), it grows by a formula that smooths the transition from 2.0x to 1.25x. (Note: Before Go 1.18, this threshold was 1024 and grew strictly by 1.25x).
- If there is a bulk append and the required capacity is strictly greater than double the current capacity, it jumps straight to the exact required capacity instead and even it round up to the next size class.
- Byte Math and Memory Rounding (Size Classes): Single element append: will double the capacity. Bulk append: will calculate the required capacity and round it up to the next size class.
This is capacity growth algorithm of append function is specifically designed to minimize the number of reallocations.
As reallocations are expensive operations.
Conclusion
Now we can understand how the append function works and why the capacity of the slice is not always equal to the length of the slice after appending.
How append function works very fast with increase in number of elements to be appended to it.
π Check out: git-lrc
Any feedback or contributors are welcome! Itβs online, open-source, and ready for anyone to use.
β Star it on GitHub:
HexmosTech
/
git-lrc
Free, Unlimited AI Code Reviews That Run on Commit
AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.
git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.
See It In Action
See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements
git-lrc-intro-60s.mp4
Why
- π€ AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production.
- π Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong.
- π Build a habit, ship better code. Regular review β fewer bugs β more robust code β better results in your team.
- π Why git? Git is universal. Every editor, every IDE, every AIβ¦
https://github.com/golang/go/blob/master/src/runtime/slice.go

Top comments (0)