We know , stay golang Medium context It's a very important bag , Save the context of the code activity . We use it a lot WithValue() This method , Dealings context in Pass on some key value data .

If we want to get context All of the key and value Or I don't know key I'd like to know more about it value How to do it ? Here's a comparison hacker For your reference .

research

First , have a look WithValue What happened :

package context

func WithValue(parent Context, key, val interface{}) Context {
return &valueCtx{parent, key, val}
} // A valueCtx carries a key-value pair. It implements Value for that key and
// delegates all other calls to the embedded Context.
type valueCtx struct {
Context
key, val interface{}
}

WithValue Through the key value Here it is valueCtx Of struct in , Save the data .

Through research context We found that , Different Functional context There are different implementations

package context

// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
cancelCtx
timer *time.Timer // Under cancelCtx.mu. deadline time.Time
} // A cancelCtx can be canceled. When canceled, it also cancels any children
// that implement canceler.
type cancelCtx struct {
Context mu sync.Mutex // protects following fields
done chan struct{} // created lazily, closed by first cancel call
children map[canceler]struct{} // set to nil by the first cancel call
err error // set to non-nil by the first cancel call
}

But without exception , It's all private struct , At the same time is through the form of linked list will each context String together .

This situation is not good for what we want to do , We can't put context The interface is converted into an implementation to get the internal saved key and value, And because there are multiple implementations , We don't know what's next context Is it right? valueCtx, Do you need to skip .

Ideas

In this case , We can only use some comparisons hacker The method of the :

  1. Define one's own valueCtx Internal data structure and context It's the same in the package
  2. adopt unsafe.Pointer() Bypass type detection , Force will context.valueCtx Into our valueCtx
  3. Get the internal value and save it in the map in

practice

First, customize one of our own valueCtx , Copy directly context It's just the realization of :

package main

type valueCtx struct {
context.Context
key, val interface{}
}

And then force it to print :

package main

func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "key1", "value1") valCtx := (*valueCtx)(unsafe.Pointer(&ctx))
fmt.Printf("key: %v, value: %v", valCtx.key, valCtx.val)
// panic: runtime error: invalid memory address or nil pointer dereference
}

It didn't happen as we expected , This is very common in programming , There must be something wrong . At this time, we should go through the materials , To understand what we're still blurring , You'll find out why . however , Since it's an article , I'll just write my conclusion .

This starts with the implementation of interface types ,golang The concept and implementation of the interface is more specific and complex , If you want to go further , Please refer to this article Stefno Of article , It's very thorough and detailed golang All aspects of the interface in . Okay , Back to our question , For now golang The interface of , We just need to know : stay golang Two things are stored in the interface of , One is the dynamic type held by the interface , The second is the value of dynamic type .

The structure is as follows :

type iface struct {
itab, data uintptr
}

in other words , When we're at the interface , In fact, it is to change the above structure into valueCtx , But in fact, we expect the data to be stored in the dynamic type value of the interface , So what we should force is iface.data.

To do that , We need to put context First convert to iface, And get the data:

package main

type iface struct {
itab, data uintptr
} type valueCtx struct {
context.Context
key, val interface{}
} func main() {
ctx := context.Background()
ctx = context.WithValue(ctx, "key1", "value1") ictx := (*iface)(unsafe.Pointer(&ctx))
valCtx := (*valueCtx)(unsafe.Pointer(ictx.data))
fmt.Printf("key: %v, value: %v", valCtx.key, valCtx.val)
// output:
// key: key1, value: value1
}

This time , We finally got the data .

perfect

Next , We need to take context All in key value Get out :

package main

func GetKeyValues(ctx context.Context) map[interface{}]interface{} {
m := make(map[interface{}]interface{})
getKeyValue(ctx, m)
return m
} func getKeyValue(ctx context.Context, m map[interface{}]interface{}) {
ictx := *(*iface)(unsafe.Pointer(&ctx))
if ictx.data == 0 {
return
} valCtx := (*valueCtx)(unsafe.Pointer(ictx.data))
if valCtx != nil && valCtx.key != nil && valCtx.val != nil {
m[valCtx.key] = valCtx.val
}
getKeyValue(valCtx.Context, m)
}

Called recursively , We can easily traverse all context, meanwhile golang Medium nil At the bottom is actually a int Of 0, That's why we put nil be called Zero value . therefore , The exit condition of recursion is also very simple , Is that when iface Medium data by 0 when , That means we've found context The last one in .

Okay , That's all , If you want to get the specific implementation and demo Example , You can come to my github Found on the , Thanks for reading .

A way to get context in keys and values An efficient way to | golang More articles about

  1. Javascript Get the maximum and minimum values in the array

    Comparing the values in an array is a common operation , Let's share four ways to get the maximum and minimum values in the array , If you are interested in this, let's study together   Comparing the values in an array is a common operation , There are many ways to compare sizes , You can use ...

  2. obtain session Methods for all values stored in

    Record in an acquisition system session What are the methods of storing objects HttpSession session = request.getSession(); for ( Enumeration e = sessi ...

  3. ASP.Net MVC Get... In the controller View Medium form Method of form value

    In website development , We often need to use the form submission method , So in MVC How to get the data in the form in ? Now let's introduce the following ways Let's first look at View Foreground page Add a controller Let's look at the code of the front page @{ La ...

  4. C# obtain url Method of parameter key value pair in

    The method is as follows : /// <summary> /// Traverse Url Parameter list in /// </summary> /// <returns> Such as :(?userName=keley ...

  5. A way to get xml The content of a node in a file shell Method

    The configuration file config.xml <xml> <server> <name>srv-01</name> </server> <serve ...

  6. Three views SqlServer In data Physics pge Page method

    1. View the file number of the current record according to the data record .page page . And the slot in the page . Examples are as follows : SELECT top %%physloc%%, sys.fn_physlocFormatter (%%physl ...

  7. php obtain post Medium json The implementation of data

    Recently, Tencent Weibo and PHP Interaction , Tencent json data post to PHP( When Tencent pushes data , Each data is a json Data packets in format , As post The data body of ( Please note that post The data body has no parameters , No key=value form , whole ...

  8. Arrangement :Javascript Get the maximum and minimum values in the array

    Method 1 : ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // minimum value Array.prototype.min = function ...

  9. android# Global access Context The technique of

    Reference resources < First line of code >—— Guo Lin Looking back on what we have learned so long , You will find that there are many places to use Context, eject Toast When you need . When starting an activity, you need . You need to . You need to ...

  10. 【 Study 】 How to use jQuery obtain iframe The elements in

    ( The original text in my blog website :http://www.xiaoxianworld.com/archives/292, Welcome to the friends you meet , Give me some comments and suggestions , There are mistakes and deficiencies , Please also point out .) Frankly speaking , It used to be very rare ...

Random recommendation

  1. [ Reprint ]CSS course : Examples explain positioning Position

    http://www.missyuan.com/thread-395406-1-1.html 1. position:static The default positioning for all elements is :position:static, This means that the elements ...

  2. hdu Collect More Jewels

    Ideas : First use bfs Get in and out , treasure , exit , The shortest distance between two . In use dfs Search for everything , Find out the maximum value you can get from the entrance to the exit . We need to solve several problems :1. Find the shortest distance from the entrance to the first place to collect the treasure 2. Please i Take... Individually ...

  3. Java Web Project development access to the last page connection address

    There's a problem with recent projects , Just need to get the last page connection address , I am using IE browser , In use location.href When connecting to a new address , On the new address page, use document.referrer Cannot get the original address , I tested it ...

  4. nginx php-cgi php

    /*************************************************************************** * nginx php-cgi php * say ...

  5. hdu 4794 FIb Find the cycle section

    It's easy to see that the problem is to find a model n In the sense of fib The smallest cyclic section of a sequence about fib The method of finding the minimum cyclic section of a sequence of numbers , We can do this : 1. Make n=p1^m1 * p2^m2 * p3^m3…… 2. Separate calculation fib The sequence is in module p1^m1 ...

  6. Codevs 4600 [NOI2015] Automatic program analysis

    4600 [NOI2015] Automatic program analysis The time limit : 1 s Space restriction : 256000 KB Question level : gold Gold Portal Title Description Description In the process of realizing automatic program analysis , Often ...

  7. Hibernate Of fetch

    hibernate Fetching strategy fetch Specific explanation 1 .hibernate Fetching strategy ( Batch fetching of single ended agents fetch=select( Default )/join) Test case :Student student = (Student ...

  8. mysql Chinese garbled

  9. Web Front end valuable blog article summary

    One .HTML Two .CSS 1. In depth understanding of position and z-index attribute :https://www.cnblogs.com/zhuzhenwei918/p/6112034.html 2.BFC( eliminate ...

  10. BZOJ2567 : Bamboo fence

    Set the first $i$ The left end of the interval is $a[i]$, The interval length is $len$, The length of the part to be covered is $all$, Because the left end of the interval is increasing , So their position in the optimal solution is still increasing . In the case of chains , Three conditions have to be met : 1. Section $i$ can ...