go-data-structures — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited go-data-structures (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
references/SLICES.md - Read when deciding nil versus empty slices, copying slices, or managing slice capacity and aliasing.What do you need?
├─ Ordered collection of items
│ ├─ Fixed size known at compile time → Array [N]T
│ └─ Dynamic size → Slice []T
│ ├─ Know approximate size? → make([]T, 0, capacity)
│ └─ Unknown size or nil-safe for JSON? → var s []T (nil)
├─ Key-value lookup
│ └─ Map map[K]V
│ ├─ Know approximate size? → make(map[K]V, capacity)
│ └─ Need a set? → map[T]struct{} (zero-size values)
└─ Need to pass to a function?
└─ Copy at the boundary if the caller might mutate itWhen this skill does NOT apply: For concurrent access to data structures (mutexes, atomic operations), see go-concurrency. For defensive copying at API boundaries, see go-defensive. For pre-sizing capacity for performance, see go-performance.
Always assign the result — the underlying array may change:
x := []int{1, 2, 3}
x = append(x, 4, 5, 6)
// Append a slice to a slice
x = append(x, y...) // Note the ...Independent inner slices (can grow/shrink independently):
picture := make([][]uint8, YSize)
for i := range picture {
picture[i] = make([]uint8, XSize)
}Single allocation (more efficient for fixed sizes):
picture := make([][]uint8, YSize)
pixels := make([]uint8, XSize*YSize)
for i := range picture {
picture[i], pixels = pixels[:XSize], pixels[XSize:]
}Prefer nil slices over empty literals:
// Good: nil slice
var t []string
// Avoid: non-nil but zero-length
t := []string{}Both have len and cap of zero, but the nil slice is the preferred style.
Exception for JSON: A nil slice encodes to null, while []string{} encodes to []. Use non-nil when you need a JSON array.
When designing interfaces, avoid distinguishing between nil and non-nil zero-length slices.
Use map[T]struct{} when the map is only a set. The empty struct takes no storage and makes membership intent explicit:
attended := map[string]struct{}{"Ann": {}, "Joe": {}}
if _, ok := attended[person]; ok {
fmt.Println(person, "was at the meeting")
}Use boolean map values only when the value carries a separate meaning beyond presence.
Be careful when copying a struct from another package. If the type has methods on its pointer type (*T), copying the value can cause aliasing bugs.
General rule: Do not copy a value of type T if its methods are associated with the pointer type *T. This applies to bytes.Buffer, sync.Mutex, sync.WaitGroup, and types containing them.
// Bad: copying a mutex
var mu sync.Mutex
mu2 := mu // almost always a bug
// Good: pass by pointer
func increment(sc *SafeCounter) {
sc.mu.Lock()
sc.count++
sc.mu.Unlock()
}| Topic | Key Point |
|---|---|
| Slices | Always assign append result; nil slice preferred over []T{} |
| Sets | map[T]struct{} for membership-only sets |
| Copying | Don't copy T if methods are on *T; beware aliasing |
new, make, var, and composite literals~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.