Search code examples
gogo-interface

Can I apply ampersand on an interface variable?


I want to create a placeholder in context object to let the downstream code to fill the error in context, so when program exiting I can capture the final error, but the following code doesn't work. I am expecting to get the address of a variable which type is error, like a C style pointer to a pointer, and fill the address with real error object later. Can someone help me that why this doesn't work as expected?


func contextWithError_test() {
    ctx := context.Background()
    ctx = contextWithFinalError(ctx)

    fillError(ctx)

    finalError := FinalErrorFromContext(ctx)
    if finalError != nil {
        fmt.Println(*finalError)
    }
}

func fillError(ctx1 context.Context) {
    var err error = errors.New("something wrong")
    finalError := FinalErrorFromContext(ctx1)
    if finalError != nil {
        finalError = &err
    }
}

func contextWithFinalError(ctx context.Context) context.Context {
    var finalError error
    return context.WithValue(ctx, finalErrorKey, &finalError)
}

func FinalErrorFromContext(ctx context.Context) *error {
    finalError, ok := ctx.Value(finalErrorKey).(*error)
    if ok {
        return finalError
    }

    return nil
}

PS I already find a way to achieve my goal, I need to declare a new type to wrap the error:

type ErrorWrapper struct {
   finalError error
}

And embed the address of an ErrorWrapper object in context. But does anyone know why the initial version doesn't work?


Solution

  • You do

        finalError := FinalErrorFromContext(ctx1)
        if finalError != nil {
            finalError = &err
        }
    

    but probably mean

        finalError := FinalErrorFromContext(ctx1)
        if finalError != nil {
            *finalError = err
        }
    

    You don't want to reassign finalError, but the variable it is pointing to.