github.com/go-board/x-go@v0.1.2-0.20220610024734-db1323f6cb15/metadata/metadata.go (about)

     1  package metadata
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  )
     7  
     8  // Metadata is an attribute list, and will be propagation to the whole call chain.
     9  // In process, will inject to context.Context.
    10  // Cross process, will serialize to header for HTTPHeader/GRPC.
    11  type Metadata map[string]string
    12  
    13  // Clone return the copy of original Metadata
    14  func (md Metadata) Clone() Metadata {
    15  	newMd := make(Metadata, len(md))
    16  	for k, v := range md {
    17  		newMd[k] = v
    18  	}
    19  	return newMd
    20  }
    21  
    22  func (md Metadata) ValueList(key string) []string { return strings.Split(md[key], ",") }
    23  
    24  var metadataKey = struct{}{}
    25  
    26  // FromContext retrieve Metadata from context.Context with default metadataKey.
    27  //
    28  // 使用默认的key从context.Context中取出Metadata,如果不存在默认的key,会发生panic
    29  func FromContext(ctx context.Context) Metadata {
    30  	return FromContextKey(ctx, metadataKey)
    31  }
    32  
    33  // FromContextKey retrieve Metadata from context.Context with given key, if nil, panic.
    34  //
    35  // 使用给定的key从context.Context中取出Metadata, 如果不存在给定的key,会发生panic
    36  func FromContextKey(ctx context.Context, key interface{}) Metadata {
    37  	return ctx.Value(key).(Metadata)
    38  }
    39  
    40  // TryFromContext retrieve Metadata from context.Context with default metadataKey.
    41  //
    42  // 尝试使用默认的key从context.Context中取出Metadata
    43  func TryFromContext(ctx context.Context) (Metadata, bool) {
    44  	return TryFromContextKey(ctx, metadataKey)
    45  }
    46  
    47  // TryFromContextKey retrieve Metadata from context.Context with given key.
    48  //
    49  // 尝试使用给定的key从context.Context中取出Metadata
    50  func TryFromContextKey(ctx context.Context, key interface{}) (Metadata, bool) {
    51  	val := ctx.Value(key)
    52  	if val == nil {
    53  		return nil, false
    54  	}
    55  	md, ok := val.(Metadata)
    56  	return md, ok
    57  }
    58  
    59  // IntoContext will append Metadata to context.Context use default metadataKey, ignore previous one.
    60  //
    61  // 使用默认的metadataKey讲Metadata注入到context.Context中,会忽略掉之前设置的。
    62  func IntoContext(ctx context.Context, md Metadata) context.Context {
    63  	return IntoContextKey(ctx, metadataKey, md)
    64  }
    65  
    66  // IntoContextKey will append Metadata to context.Context use given key, ignore previous one.
    67  //
    68  // 使用给定的key讲Metadata注入到context.Context中, 会忽略掉之前设置的。
    69  func IntoContextKey(ctx context.Context, key interface{}, md Metadata) context.Context {
    70  	return context.WithValue(ctx, key, md)
    71  }
    72  
    73  // MergeIntoContext will append Metadata to context.Context use default metadataKey, if has previous one, merge then update.
    74  //
    75  // 使用默认的metadataKey讲Metadata注入到context.Context中,如果存在上一个,先合并再更新
    76  func MergeIntoContext(ctx context.Context, md Metadata) context.Context {
    77  	oldOne, ok := TryFromContext(ctx)
    78  	if !ok {
    79  		return IntoContext(ctx, md)
    80  	}
    81  	for k, v := range oldOne {
    82  		md[k] = v
    83  	}
    84  	return IntoContext(ctx, md)
    85  }
    86  
    87  // MergeIntoContextKey will append Metadata to context.Context use default metadataKey, if has previous one, merge then update.
    88  //
    89  // 使用给定的keyey讲Metadata注入到context.Context中,如果存在上一个,先合并再更新
    90  func MergeIntoContextKey(ctx context.Context, key interface{}, md Metadata) context.Context {
    91  	oldOne, ok := TryFromContextKey(ctx, key)
    92  	if !ok {
    93  		return IntoContextKey(ctx, key, md)
    94  	}
    95  	for k, v := range oldOne {
    96  		md[k] = v
    97  	}
    98  	return IntoContextKey(ctx, key, md)
    99  }