第五节 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. }

19. // Move cursor to correct position.
20. c := b.Cursor()
21. k, _, flags := c.seek(key)

23. // Return an error if there is an existing key with a bucket value.
24. if bytes.Equal(key, k) && (flags&bucketLeafFlag) != 0 {
25. return ErrIncompatibleValue
26. }

28. // Insert into node.
29. key = cloneBytes(key)
30. c.node().put(key, key, value, 0, 0)

32. return nil
33. }

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)

7. // Return nil if this is a bucket.
8. if (flags & bucketLeafFlag) != 0 {
9. return nil
10. }

12. // If our target node isn't the same key as what's passed in then return nil.
13. if !bytes.Equal(key, k) {
14. return nil
15. }
16. return v
17. }

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. }

11. // Move cursor to correct position.
12. c := b.Cursor()
13. _, _, flags := c.seek(key)

15. // Return an error if there is already existing bucket value.
16. if (flags & bucketLeafFlag) != 0 {
17. return ErrIncompatibleValue
18. }

20. // Delete the node if we have a matching key.
21. c.node().del(key)

23. return nil
24. }

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. }