
Go Data Structures
Apply Effective Go slice semantics—pointer, length, capacity, sharing, and append—while implementing or reviewing Go backend code.
Overview
Go Data Structures is an agent skill for the Build phase that teaches slice internals from Effective Go so backend Go code avoids aliasing and append pitfalls.
Install
npx skills add https://github.com/cxuu/golang-skills --skill go-data-structuresWhat is this skill?
- Explains the three-item slice descriptor: pointer, length, capacity
- Shows shared underlying array mutations across sub-slices
- Documents slice operator forms including three-index `lo:hi:max` capacity limits
- Clarifies why append must return the slice header after reallocation
- Sourced from Effective Go for idiomatic Go backend work
- Slice descriptor has 3 components: pointer, length, capacity
Adoption & trust: 650 installs on skills.sh; 110 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent keeps generating Go slice code that mutates shared backing arrays or drops append results because slice headers are passed by value.
Who is it for?
Indie Go developers who want the agent to cite real slice semantics while building APIs, parsers, or in-memory pipelines.
Skip if: Greenfield projects in other languages, high-level product planning, or teams that need full data-structure course coverage beyond slices.
When should I use this skill?
Invoke when implementing or reviewing Go code involving slices, append, sub-slice sharing, or capacity-limited slicing.
What do I get? / Deliverables
Implementations use correct slicing, capacity limits, and append patterns aligned with Effective Go, reducing subtle data corruption in Go services.
- Corrected or newly written Go functions using idiomatic slice patterns
- Review comments that flag shared backing-array hazards
Recommended Skills
Journey fit
Slice behavior matters during implementation when agents generate Go services, CLIs, or data handlers—not during early ideation. Backend subphase is where slice aliasing, append growth, and three-index forms affect correctness and performance.
How it compares
Focused Effective Go slice reference—not a generic algorithms or LeetCode patterns pack.
Common Questions / FAQ
Who is go-data-structures for?
Solo builders writing Go backend or CLI code who need accurate slice behavior in agent-assisted implementation and review.
When should I use go-data-structures?
Use it in Build (backend) when editing functions that slice, append, or share backing arrays—including Ship review passes on Go PRs that touch buffer logic.
Is go-data-structures safe to install?
It is documentation-only reference content with no shell or network requirements; still review the Security Audits panel on this page for the package as a whole.
SKILL.md
READMESKILL.md - Go Data Structures
# Go Slice Internals > **Source**: Effective Go --- ## The Three-Item Descriptor A slice is a runtime data structure with three components: - **Pointer**: Address of the first accessible element - **Length**: Number of elements (`len(s)`) - **Capacity**: Max elements to end of underlying array (`cap(s)`) ```go arr := [5]int{10, 20, 30, 40, 50} s := arr[1:4] // s = [20, 30, 40] // pointer: &arr[1], length: 3, capacity: 4 ``` A `nil` slice has all three items set to zero/nil. --- ## Slices Reference Underlying Arrays Slices don't store data—they describe a section of an array: ```go data := [4]int{1, 2, 3, 4} a := data[0:2] // [1, 2] b := data[1:3] // [2, 3] b[0] = 99 fmt.Println(a) // [1, 99] - both see the change fmt.Println(data) // [1, 99, 3, 4] ``` --- ## The Slice Operator `s[lo:hi]` creates a slice from index `lo` to `hi-1`: ```go s := []int{0, 1, 2, 3, 4, 5} s[2:4] // [2, 3] s[:3] // [0, 1, 2] s[3:] // [3, 4, 5] ``` Three-index form `s[lo:hi:max]` limits capacity to `max-lo`. --- ## Why append Must Return the Slice The slice header is passed **by value**. Functions can modify elements but cannot change the caller's header: ```go func Append(slice, data []byte) []byte { l := len(slice) if l+len(data) > cap(slice) { newSlice := make([]byte, (l+len(data))*2) copy(newSlice, slice) slice = newSlice // Only changes local variable } slice = slice[0 : l+len(data)] copy(slice[l:], data) return slice // Caller must receive the new header } ``` When reallocation occurs, `slice` points to a new array. The caller's original still points to the old one—returning lets them update their reference. --- ## The copy Function `copy(dst, src)` copies elements and returns the count copied: ```go src := []int{1, 2, 3, 4, 5} dst := make([]int, 3) n := copy(dst, src) // n=3, dst=[1,2,3] ``` Handles overlapping slices correctly. Copies `min(len(dst), len(src))` elements—no reallocation occurs. --- ## Slice Gotchas ### 1. Shared Underlying Array ```go original := []int{1, 2, 3, 4, 5} subset := original[1:3] subset[0] = 99 fmt.Println(original) // [1, 99, 3, 4, 5] - modified! // Fix: make independent copy subset := make([]int, 2) copy(subset, original[1:3]) ``` ### 2. Append May or May Not Reallocate ```go a := make([]int, 3, 5) // len=3, cap=5 b := a[0:3] a = append(a, 4) // Fits in capacity - still shared a = append(a, 5, 6) // Exceeds capacity - now independent ``` ### 3. Memory Leaks from Large Backing Arrays ```go // Bad: small slice keeps entire file in memory func getHeader(file []byte) []byte { return file[:100] } // Good: copy to release the large array func getHeader(file []byte) []byte { header := make([]byte, 100) copy(header, file) return header } ``` ### 4. Nil vs Empty Slice ```go var nilSlice []int // nil, len=0, cap=0 emptySlice := []int{} // non-nil, len=0, cap=0 // Both work identically with len, cap, append, range // Prefer nil for uninitialized state ``` ## Quick Reference | Operation | Behavior | |-----------|----------| | `s[lo:hi]` | Slice from lo to hi-1 | | `s[lo:hi:max]` | Slice with capacity limited to max-lo | | `append(s, x...)` | Returns new slice; may reallocate | | `copy(dst, src)` | Returns count copied; no reallocation | --- name: go-data-structures description: Use when working with Go slices, maps, or arrays — choosing between new and make, using append, declaring empty slices (nil vs literal for JSON), implementing sets with maps, and copying data at boundaries. Also use when building or manipulating collections, even if the user doesn't ask about allocation idioms. Does not cover concurrent data structure safety (see go-concurrency). license: Apache-2.0 metadata: sources: "Effective Go, Google Style Guide, Uber Style Guide, Go Wiki CodeReviewComments" --- # Go Data Structures --- ## Choosing a Data Structure ``` What do you need? ├─ Ordered collection of items │ ├─ Fixed size