A lightweight and idiomatic Go library that captures and formats caller information such as file name, line number, function name, and package path.
Perfect for use in:
- Custom error types
- Logging wrappers
- Debugging utilities
- Tracing and instrumentation
- Minimal and dependency-free
- Clean, consistent API with platform-independent file paths
- Get full or short location (
file:line) - Extract function name, full function path, and package info
- Implements
fmt.Stringerinterface for easy logging - Implements
json.Marshalerandjson.Unmarshalerinterfaces for easy JSON serialization - Implements
slog.LogValuerinterface for structured logging - Semantic equality comparison between callers
go get github.com/balinomad/go-caller/v2@latestimport "github.com/balinomad/go-caller/v2"
func someFunc() {
c := caller.Immediate()
// Check validity
if c.Valid() {
fmt.Println("Caller information is valid")
}
// Basic information
fmt.Println("Caller location:", c.Location())
fmt.Println("Short:", c.ShortLocation())
fmt.Println("Function:", c.Function())
fmt.Println("Package:", c.PackageName())
}| Function | Description |
|---|---|
Immediate() Caller |
Returns caller info for the immediate caller |
New(skip int) Caller |
Returns caller info with custom stack skip depth |
NewFromPC(pc uintptr) Caller |
Creates caller info from a program counter |
| Method | Description | Example Output |
|---|---|---|
Valid() bool |
Returns true if the caller info is usable | true/false |
File() string |
Full file path | /path/to/file.go |
Line() int |
Line number | 42 |
Location() string |
Full location with file:line | /path/to/file.go:42 |
ShortLocation() string |
Short location with just filename:line | file.go:42 |
Function() string |
Function/method name without package | MyFunction |
FullFunction() string |
Full function name including package | github.com/user/pkg.MyFunction |
Package() string |
Full import path of the package | github.com/user/pkg |
PackageName() string |
Last element of the package path | pkg |
Equal(other Caller) bool |
Checks if two callers are semantically equal | true/false |
String() string |
Returns ShortLocation() (implements fmt.Stringer) |
file.go:42 |
MarshalJSON() ([]byte, error) |
Marshals caller info to JSON | {"file":"...","line":42,...} |
UnmarshalJSON([]byte) error |
Unmarshals JSON to caller info | - |
LogValue() slog.Value |
Returns structured value for slog | {file:..., line:42, ...} |
// Skip 0 = immediate caller (same as Immediate())
// Skip 1 = caller of the immediate caller
// Skip 2 = caller of the caller, etc.
c := caller.New(2)pc, _, _, _ := runtime.Caller(0)
c := caller.NewFromPC(pc)// Marshal
c := caller.Immediate()
jsonData, err := json.Marshal(c)
// Output: {"file":"main.go","line":10,"function":"main","package":"main"}
// Unmarshal
var c2 caller.Caller
err = json.Unmarshal(jsonData, &c2)logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
c := caller.Immediate()
logger.Info("user action",
slog.String("action", "login"),
slog.String("caller", c.Location()),
slog.String("func", c.Function()))
// Output includes structured caller informationc1 := caller.Immediate()
// ... some other code ...
c2 := caller.Immediate()
if c1.Equal(c2) {
fmt.Println("Called from the same location")
} else {
fmt.Println("Called from different locations")
}Valid()behavior: Now only requires a non-empty file path (previously required file, line, and function)New()edge cases: Only returnsnilfor negative skip values
- Added
Equal()method for comparing callers - Improved performance and error handling
- Comprehensive test coverage
// v1 code that might need review
c := caller.New(0)
if c.Valid() {
// In v1: Valid only if file, line, AND function are present
// In v2: Valid if file is present (more permissive)
}
// New v2 feature
if c1.Equal(c2) {
// Semantic comparison of callers
}The library is designed to be lightweight with minimal allocations:
- Zero dependencies beyond Go standard library
- Optimized string operations
- Efficient memory usage with
uint16for line numbers - Comprehensive benchmarks included in tests
Run tests with:
go test -vRun benchmarks with:
go test -bench=. -benchmemMIT License — see LICENSE file for details.