所以,我有一个 context.Context( https://golang.org/pkg/context/ ) 变量,有没有办法列出这个变量保存的所有键?
Rob*_*son 13
可以使用不安全反射列出 context.Context 的内部结构,并使用该信息找出键和/或查看您想要的信息是否在上下文中。
有一些陷阱,例如如果上下文实现返回一个硬编码的键值,它不会在此处显示,并且可能不清楚如何使用键实际访问这些值。
这不是我在生产中运行的。但就我而言,我需要能够检查 context.Context 以更好地了解它包含的信息。
func printContextInternals(ctx interface{}, inner bool) {
contextValues := reflect.ValueOf(ctx).Elem()
contextKeys := reflect.TypeOf(ctx).Elem()
if !inner {
fmt.Printf("\nFields for %s.%s\n", contextKeys.PkgPath(), contextKeys.Name())
}
if contextKeys.Kind() == reflect.Struct {
for i := 0; i < contextValues.NumField(); i++ {
reflectValue := contextValues.Field(i)
reflectValue = reflect.NewAt(reflectValue.Type(), unsafe.Pointer(reflectValue.UnsafeAddr())).Elem()
reflectField := contextKeys.Field(i)
if reflectField.Name == "Context" {
printContextInternals(reflectValue.Interface(), true)
} else {
fmt.Printf("field name: %+v\n", reflectField.Name)
fmt.Printf("value: %+v\n", reflectValue.Interface())
}
}
} else {
fmt.Printf("context is empty (int)\n")
}
}
Run Code Online (Sandbox Code Playgroud)
例子:
func Ping(w http.ResponseWriter, r *http.Request) {
printContextInternals(r.Context(), false)
/* Prints
Fields for context.valueCtx
context is empty (int)
field name: key
value: net/http context value http-server
field name: val
value: &{Addr::20885 Handler:0xc00001c000 TLSConfig:0xc000001c80 ReadTimeout:0s ReadHeaderTimeout:0s WriteTimeout:0s IdleTimeout:0s MaxHeaderBytes:0 TLSNextProto:map[h2:0x12db010] ConnState:<nil> ErrorLog:<nil> BaseContext:<nil> ConnContext:<nil> disableKeepAlives:0 inShutdown:0 nextProtoOnce:{done:1 m:{state:0 sema:0}} nextProtoErr:<nil> mu:{state:0 sema:0} listeners:map[0xc00015a840:{}] activeConn:map[0xc000556fa0:{}] doneChan:<nil> onShutdown:[0x12e9670]}
field name: key
value: net/http context value local-addr
field name: val
value: [::1]:20885
field name: mu
value: {state:0 sema:0}
field name: done
value: 0xc00003c2a0
field name: children
value: map[context.Background.WithValue(type *http.contextKey, val <not Stringer>).WithValue(type *http.contextKey, val [::1]:20885).WithCancel.WithCancel:{}]
field name: err
value: <nil>
field name: mu
value: {state:0 sema:0}
field name: done
value: <nil>
field name: children
value: map[]
field name: err
value: <nil>
field name: key
value: 0
field name: val
value: map[]
field name: key
value: 1
field name: val
value: &{handler:0x151cf50 buildOnly:false name: err:<nil> namedRoutes:map[] routeConf:{useEncodedPath:false strictSlash:false skipClean:false regexp:{host:<nil> path:0xc0003d78f0 queries:[]} matchers:[0xc0003d78f0 [GET POST]] buildScheme: buildVarsFunc:<nil>}}
*/
printContextInternals(context.Background(), false)
/* Prints
Fields for context.emptyCtx
context is empty (int)
*/
}
Run Code Online (Sandbox Code Playgroud)
不,没有办法列出 的所有键context.Context
。因为该类型只是一个接口。那么这是什么意思?
一般来说,变量可以保存具体类型或接口。具有接口类型的变量没有任何具体的类型信息。因此,如果接口为空 ( ) 或 context.Context 都没有什么区别interface{}
。因为它们可能是实现该接口的许多不同类型。该变量没有具体类型。这只是一些抽象的东西。
如果您使用反射,您可以观察设置为该变量(具有接口类型)的类型的字段和所有方法。但该方法的实现逻辑Value(key interface{}) interface{}
并不固定。它不一定是地图。您还可以使用切片、数据库、自己类型的哈希表等进行实现。
因此没有通用的方法来列出所有值。
归档时间: |
|
查看次数: |
4225 次 |
最近记录: |