Skip to content

feat: add optional skip argument to Helper function #175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

xStrom
Copy link

@xStrom xStrom commented Jun 21, 2025

The problem

The current Helper function is hardcoded to only skip the immediate function that called it. This makes it really unergonomic to use in an abstraction.

I have an abstraction type which provides a bunch of convenience methods, e.g. extracts known values from context.Context and passes them as attributes to the various log functions. This abstraction also manages multiple different instances of Logger under the hood. It all works quite well, except when it comes to Helper.

Broken abstraction

func AbstractedHelper() {
    // Calling the Helper function on these Logger instances
    // will just mark AbstractedHelper for skipping.
    loggerA.Helper()
    loggerB.Helper()
}

func example() {
    common()
}

func common() {
    AbstractedHelper()
    Info("Hello") // Incorrectly prints this line as the source
}

Working but unergonomic abstraction

func AbstractedHelper() []func() {
    // Don't call the functions yet, just return them.
    return []func(){loggerA.Helper, loggerB.Helper}
}

func example() {
    common() // Correctly prints this line as the source
}

func common() {
    for _, helper := range AbstractedHelper() {
        helper()
    }
    Info("Hello")
}

The solution

The internal helper function already takes a skip argument that would solve this issue. The public function doesn't yet expose this and that is exactly what this PR does.

In order to achieve backwards compatibility, the skip argument will be optional by making the public Helper a variadic function.

Ergonomic abstraction achieved

func AbstractedHelper() {
    // We tell Helper to also skip the abstraction function
    loggerA.Helper(2)
    loggerB.Helper(2)
}

func example() {
    common() // Correctly prints this line as the source
}

func common() {
    AbstractedHelper()
    Info("Hello")
}

@xStrom xStrom requested a review from aymanbagabas as a code owner June 21, 2025 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant