{"record":{"id":"eb6084741ffd6c3e","repo":"unknwon/the-way-to-go_ZH_CN","slug":"stack-is-empty","errorCode":null,"errorMessage":"stack is empty","messagePattern":"stack is empty","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"eBook/exercises/chapter_11/stack/stack_general.go","lineNumber":26,"sourceCode":"func (stack Stack) Len() int {\n\treturn len(stack)\n}\n\nfunc (stack Stack) Cap() int {\n\treturn cap(stack)\n}\n\nfunc (stack Stack) IsEmpty() bool {\n\treturn len(stack) == 0\n}\n\nfunc (stack *Stack) Push(e interface{}) {\n\t*stack = append(*stack, e)\n}\n\nfunc (stack Stack) Top() (interface{}, error) {\n\tif len(stack) == 0 {\n\t\treturn nil, errors.New(\"stack is empty\")\n\t}\n\treturn stack[len(stack)-1], nil\n}\n\nfunc (stack *Stack) Pop() (interface{}, error) {\n\tstk := *stack // dereference to a local variable stk\n\tif len(stk) == 0 {\n\t\treturn nil, errors.New(\"stack is empty\")\n\t}\n\ttop := stk[len(stk)-1]\n\t*stack = stk[:len(stk)-1] // shrink the stack\n\treturn top, nil\n}\n","sourceCodeStart":8,"sourceCodeEnd":40,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/exercises/chapter_11/stack/stack_general.go#L8-L40","documentation":"Error returned by Top() in the Chapter 11 generic stack exercise (Stack is a []interface{}). Top() is the non-destructive peek: it returns the last element, and when len(stack) == 0 there is nothing to peek, so instead of indexing into an empty slice it returns (nil, this error). The package teaches the idiomatic Go pattern of returning (value, error) from container accessors rather than panicking.","triggerScenarios":"Calling Top() on a zero-length Stack: a freshly declared stack (var s Stack), one that was never Pushed, or one fully drained because each Pop() shrinks the slice with *stack = stk[:len(stk)-1].","commonSituations":"Delimiter-matching or expression-evaluation algorithms that peek assuming an opening item remains; loops that read one element past end of input; reusing a stack field across requests without re-checking emptiness; assuming Top() returns zero quietly instead of an error.","solutions":["Call stack.IsEmpty() (value receiver, len(stack)==0) before Top() and skip or report empty input when true","Always take both return values: if v, err := s.Top(); err != nil { /* empty */ } else { use v }","If it fires inside a loop, re-check the invariant: the number of Top() calls must never exceed the number of live Push() calls (every Top should correspond to a previously unmatched Push)","Restructure the caller so Top() only runs in a branch that just successfully Push()ed, guaranteeing non-emptiness"],"exampleFix":"// before\nval := s.Top() // error ignored; val is nil on empty stack\n\n// after\nval, err := s.Top()\nif err != nil {\n\treturn fmt.Errorf(\"nothing to read: %v\", err)\n}\n_ = val","handlingStrategy":"validation","validationCode":"if s.IsEmpty() {\n\treturn nil // caller-level: nothing to peek\n}\nv, err := s.Top()\nif err != nil {\n\treturn err\n}","typeGuard":null,"tryCatchPattern":"v, err := s.Top()\nif err != nil {\n\t// stack is empty: skip, report, or terminate this branch\n\treturn err\n}\n// use v","preventionTips":["Bind and check both return values of every Top() call; never assume a preceding Push guarantees state across refactors","Check IsEmpty() at loop boundaries where input can end before the algorithm expects","Do not bypass Top() by indexing the exported slice type directly — that skips the emptiness guard and panics","If callers need errors.Is classification, wrap the stack with your own exported ErrEmptyStack; the exercise defines no exported error variable"],"tags":["go","stack","data-structures","empty-state"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}