Golang中如何打印调用函数的参数值
Golang中如何打印调用函数的参数值 我可以打印调用者函数的名称,但我想要获取调用者函数的参数,这在Go语言中是否可能实现。 我在此附上我的代码供您参考。
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:]
// 我可以打印funcName,但我想要调用者函数的参数。调用者函数的参数 (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)
}
上述代码的输出是:
called from callerFunction
Value of z is 7
更多关于Golang中如何打印调用函数的参数值的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这个方案对你有效吗?https://play.golang.org/p/Drcip-PgXQo
更多关于Golang中如何打印调用函数的参数值的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
httpRequestBuilder 正在调用另一个函数(func1()),但没有传递上下文(ctx)。现在我想在 func1 中访问这个上下文,我该怎么做?
您不能这样做。除非您有某种副作用,例如将其赋值给一个全局变量,稍后再从您的无参函数中读取它。您无法访问调用者的栈帧并获取其参数,而且我仍然不明白您为什么不直接显式地传递它。
我怀疑这是不可能的:Go 有一个内部 ABI,它并不要求所有函数参数都通过栈传递,因此即使在运行时检查调用函数的栈帧(如果它被内联了,可能根本就没有栈帧),它也可能实际上没有为你要查找的变量预留空间。
你为什么要这样做呢?
我在提取调用者函数的上下文值时遇到了问题。简单来说,我在一个上下文中设置了一个值,然后将该上下文设置到一个请求中,将请求的副本传递给代码流程,之后当我尝试从请求中提取该值时,却无法获取到该值。因此,我试图做的是提取传递给函数的请求,以便我可以从该请求中获取上下文。
将请求的副本传递给了代码流程
我不明白你这是什么意思,但我想提两点:
- 上下文不会在 HTTP 请求和响应之间复制。你必须自己处理将值序列化到/从 HTTP 请求/响应中。
- 向上下文添加值会创建一个新的上下文;原始的上下文不会被修改,所以当你说
ctx2 := context.WithValue(ctx1, k, v)时,ctx1并不包含k和v这对新的键值,只有ctx2包含。
我还是不确定你想做什么,为什么你不能直接显式地传递上下文呢?
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")
// 必须更新 req.Context 以包含我们的新值:
req = req.WithContext(ctx)
req = doSomething(ctx, req)
}
func doSomething(ctx context.Context, req *http.Request) *http.Request {
// 这里应该可以访问 myKeyType
v := ctx.Value(myKeyType("test")).(string)
// v == "Hello, world"
return req
}
在Go语言中,直接获取调用者函数的参数值并不直接支持,因为运行时信息中不包含参数值。不过,可以通过反射和自定义调用栈信息来间接实现。以下是一个示例,演示如何通过传递参数到跟踪函数来打印调用者函数的参数:
package main
import (
"fmt"
"runtime"
"reflect"
)
func foo(args ...interface{}) {
pc, _, _, ok := runtime.Caller(1)
details := runtime.FuncForPC(pc)
if ok && details != nil {
funcName := details.Name()
fmt.Printf("called from %s with args: ", funcName)
for i, arg := range args {
fmt.Printf("%v", arg)
if i < len(args)-1 {
fmt.Print(", ")
}
}
fmt.Println()
}
}
func callerFunction(x int) int {
foo(x) // 显式传递参数
return x + 2
}
func anotherCaller(y string, z float64) {
foo(y, z) // 传递多个参数
}
func main() {
z := callerFunction(5)
fmt.Printf("Value of z is %d\n", z)
anotherCaller("test", 3.14)
}
输出:
called from main.callerFunction with args: 5
Value of z is 7
called from main.anotherCaller with args: test, 3.14
如果必须自动获取参数而不显式传递,可以使用反射结合自定义包装器,但这种方法复杂且有限制。以下是一个高级示例,使用反射获取参数值(仅适用于已知函数签名):
package main
import (
"fmt"
"reflect"
)
func captureArgs(fn interface{}, args ...interface{}) {
fnValue := reflect.ValueOf(fn)
if fnValue.Kind() != reflect.Func {
panic("not a function")
}
fnType := fnValue.Type()
if fnType.NumIn() != len(args) {
panic("argument count mismatch")
}
callArgs := make([]reflect.Value, len(args))
for i, arg := range args {
callArgs[i] = reflect.ValueOf(arg)
}
fmt.Print("calling with args: ")
for i, arg := range args {
fmt.Printf("%v", arg)
if i < len(args)-1 {
fmt.Print(", ")
}
}
fmt.Println()
results := fnValue.Call(callArgs)
for _, result := range results {
fmt.Printf("result: %v\n", result)
}
}
func exampleFunc(x int, y string) string {
return fmt.Sprintf("%d-%s", x, y)
}
func main() {
captureArgs(exampleFunc, 42, "hello")
}
输出:
calling with args: 42, hello
result: 42-hello
注意:这些方法都需要在调用时显式处理参数,因为Go的运行时不会自动暴露参数值。

