github.com/duomi520/utils@v0.0.0-20240430123446-e03a4cddd6ec/dict.go (about)

     1  package utils
     2  
     3  import (
     4  	"encoding/binary"
     5  )
     6  
     7  type ky struct {
     8  	key   uint64
     9  	value string
    10  }
    11  
    12  // MetaDict 非线程安全,key数量超过5个后,效率低于map
    13  type MetaDict []ky
    14  
    15  // GetAll
    16  func (d MetaDict) GetAll() (s []string) {
    17  	for _, k := range d {
    18  		s = append(s, k.value)
    19  	}
    20  	return s
    21  }
    22  
    23  func (d MetaDict) findIndex(hash uint64) int {
    24  	for i, k := range d {
    25  		if k.key == hash {
    26  			return i
    27  		}
    28  	}
    29  	return -1
    30  }
    31  
    32  // Set 设置给定键的值,如果该键已存在,则更新值;如果不存在,则添加新的键值对。
    33  func (d MetaDict) Set(key, value string) (new MetaDict) {
    34  	hash := Hash64FNV1A(key)
    35  	if idx := d.findIndex(hash); idx != -1 {
    36  		d[idx].value = value
    37  		return d
    38  	}
    39  	new = append(d, ky{hash, value})
    40  	return new
    41  }
    42  
    43  // Get 根据给定的键返回相应的值。如果键存在,则返回对应的值和true;如果键不存在,则返回空字符串和false。
    44  func (d MetaDict) Get(key string) (string, bool) {
    45  	hash := Hash64FNV1A(key)
    46  	if idx := d.findIndex(hash); idx != -1 {
    47  		return d[idx].value, true
    48  	}
    49  	return "", false
    50  }
    51  
    52  // Del 根据给定的键删除相应的键值对。
    53  func (d MetaDict) Del(key string) (new MetaDict) {
    54  	hash := Hash64FNV1A(key)
    55  	if idx := d.findIndex(hash); idx != -1 {
    56  		if idx < (len(d) - 1) {
    57  			copy(d[idx:], d[idx+1:])
    58  		}
    59  		return d[:len(d)-1]
    60  	}
    61  	return d
    62  }
    63  
    64  /*
    65  +-------+-------+-------+-------+-------+-------+
    66  | len(8)|        key (64)       |    value      |  ...
    67  +-------+-------+-------+-------+-------+-------+
    68  */
    69  
    70  // Encode 编码 将字典编码为字节切片。
    71  func MetaDictEncode(d MetaDict) []byte {
    72  	size := len(d)
    73  	if size == 0 {
    74  		return nil
    75  	}
    76  	n := 0
    77  	for i := 0; i < size; i++ {
    78  		n += 1 + 8 + len(d[i].value)
    79  	}
    80  	buf := make([]byte, n)
    81  	idx := 0
    82  	for i := 0; i < size; i++ {
    83  		buf[idx] = byte(1 + 8 + len(d[i].value))
    84  		idx++
    85  		binary.LittleEndian.PutUint64(buf[idx:], d[i].key)
    86  		idx += 8
    87  		copy(buf[idx:], StringToBytes(d[i].value))
    88  		idx += len(d[i].value)
    89  	}
    90  	return buf
    91  }
    92  
    93  // Decode 解码 将字节切片解码为字典。
    94  func MetaDictDecode(data []byte) (d MetaDict) {
    95  	idx := 0
    96  	for len(data) > idx {
    97  		n := int(data[idx])
    98  		d = append(d, ky{binary.LittleEndian.Uint64(data[idx+1 : idx+1+8]), string(data[idx+1+8 : idx+n])})
    99  		idx += n
   100  	}
   101  	return d
   102  }