Is it possible to print the value of caller function parameter?

I am able to print the name of the caller function, but I want to extract the parameter of the caller function, is it possible to do that in Go.
I’m attaching my code here for your reference.

package main

import (
    "fmt"
    "runtime"
)

func foo() {
    pc, _, _, ok := runtime.Caller(1)
    details := runtime.FuncForPC(pc)
    var funcName string
    if ok && details != nil {
        funcName = details.Name()[5:]
        // I am able to print the funcName but I want the parameter of caller
        // function. callerFunction's parameter (x)
        fmt.Printf("called from %s\n", funcName)
    }
}

func callerFunction(x int)(int){
        foo()
        return x + 2
}

func main() {
        z := callerFunction(5)
        fmt.Printf("Value of z is %d\n",z)
}

The output of the above code is:

called from callerFunction

Value of z is 7

I doubt this is possible: Go has an internal ABI that doesn’t require all function parameters to be passed on the stack, so even if you inspected the calling function’s frame at runtime (which it might not have, if it was inlined), it might not actually have a space for the variable you’re looking for.

Why would you want to do this?

I am having an issue in extracting the context value of the caller function. In simple words, I set a value inside a context, then I set that context in a request, passed the copy of the request to the code flow, later when I tried extracting the value from the request I’m not able to get that value. So, what I’m trying to do is to extract the request which was passed to the function, so that I can get the context from that request.

I don’t know what you mean by this, but I want to mention two things:

  1. Contexts are not copied between HTTP requests and responses. You have to handle serializing the values to/from the HTTP Request/response yourself.
  2. Adding a value to a context creates a new context; the original is not modified, so when you say: ctx2 := context.WithValue(ctx1, k, v), then ctx1 doesn’t doesn’t have the new key and value pair for k and v, only ctx2 does.

I’m still not sure what you’re trying to do, why can’t you just pass the context explicitly?

type myKeyType string

func httpRequestBuilder(ctx context.Context) (*http.Request, error) {
    req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://example.com/", nil)
    if err != nil {
        return nil, err
    }
    ctx = context.WithValue(ctx, myKeyType("test"), "Hello, world")
    // have to update req.Context to include our new value:
    req = req.WithContext(ctx)
    req = doSomething(ctx, req)
}

func doSomething(ctx context.Context, req *http.Request) *http.Request {
    // Should have access to myKeyType here
    v := ctx.Value(myKeyType("test")).(string)
    // v == "Hello, world"
    return req
}

httpRequestBuilder is calling another function (func1()) and doesn’t pass the ctx, now I want to access this context in func1, how will I do that?

You cannot. Unless you have some sort of side effect, like assign it to a global and read it back from your niladic function later. You cannot reach into a caller’s frame and access its parameters, though and I still don’t understand why you don’t just pass it explicitly.

Does this work for you? https://play.golang.org/p/Drcip-PgXQo

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.