第五节 key/value的插入、获取、删除

上面一节我们介绍了一下如何创建一个Bucket、如何获取一个Bucket。有了Bucket,我们就可以对我们最关心的key/value键值对进行增删改查了。其实本质上,对key/value的所有操作最终都要表现在底层的node上。因为node节点就是用来存储真实数据的。

3.5.1 插入一个key/value对

  1. // Put sets the value for a key in the bucket.
  2. // If the key exist then its previous value will be overwritten.
  3. // Supplied value must remain valid for the life of the transaction.
  4. // Returns an error if the bucket was created from a read-only transaction,
  5. // if the key is blank, if the key is too large, or if the value is too large.
  6. func (b *Bucket) Put(key []byte, value []byte) error {
  7. if b.tx.db == nil {
  8. return ErrTxClosed
  9. } else if !b.Writable() {
  10. return ErrTxNotWritable
  11. } else if len(key) == 0 {
  12. return ErrKeyRequired
  13. } else if len(key) > MaxKeySize {
  14. return ErrKeyTooLarge
  15. } else if int64(len(value)) > MaxValueSize {
  16. return ErrValueTooLarge
  17. }
  18. // Move cursor to correct position.
  19. c := b.Cursor()
  20. k, _, flags := c.seek(key)
  21. // Return an error if there is an existing key with a bucket value.
  22. if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 {
  23. return ErrIncompatibleValue
  24. }
  25. // Insert into node.
  26. key = cloneBytes(key)
  27. c.node().put(key, key, value, 0, 0)
  28. return nil
  29. }

3.5.2 获取一个key/value对

  1. // Get retrieves the value for a key in the bucket.
  2. // Returns a nil value if the key does not exist or if the key is a nested bucket.
  3. // The returned value is only valid for the life of the transaction.
  4. func (b *Bucket) Get(key []byte) []byte {
  5. k, v, flags := b.Cursor().seek(key)
  6. // Return nil if this is a bucket.
  7. if (flags & bucketLeafFlag) != 0 {
  8. return nil
  9. }
  10. // If our target node isn't the same key as what's passed in then return nil.
  11. if !bytes.Equal(key, k) {
  12. return nil
  13. }
  14. return v
  15. }

3.5.3 删除一个key/value对

  1. // Delete removes a key from the bucket.
  2. // If the key does not exist then nothing is done and a nil error is returned.
  3. // Returns an error if the bucket was created from a read-only transaction.
  4. func (b *Bucket) Delete(key []byte) error {
  5. if b.tx.db == nil {
  6. return ErrTxClosed
  7. } else if !b.Writable() {
  8. return ErrTxNotWritable
  9. }
  10. // Move cursor to correct position.
  11. c := b.Cursor()
  12. _, _, flags := c.seek(key)
  13. // Return an error if there is already existing bucket value.
  14. if (flags & bucketLeafFlag) != 0 {
  15. return ErrIncompatibleValue
  16. }
  17. // Delete the node if we have a matching key.
  18. c.node().del(key)
  19. return nil
  20. }

3.5.4 遍历Bucket中所有的键值对

  1. // ForEach executes a function for each key/value pair in a bucket.
  2. // If the provided function returns an error then the iteration is stopped and
  3. // the error is returned to the caller. The provided function must not modify
  4. // the bucket; this will result in undefined behavior.
  5. func (b *Bucket) ForEach(fn func(k, v []byte) error) error {
  6. if b.tx.db == nil {
  7. return ErrTxClosed
  8. }
  9. c := b.Cursor()
  10. // 遍历键值对
  11. for k, v := c.First(); k != nil; k, v = c.Next() {
  12. if err := fn(k, v); err != nil {
  13. return err
  14. }
  15. }
  16. return nil
  17. }