Go中Dictionary數據結構的分析與實現
詞典商店[key, value]
對。 Go通過內置的字典提供了非常方便的字典實現map
類型。
在本文中,我將豐富map
內置類型,並通過一些方便的操作來獲取其中的信息並更改其內容。
我將創建一個ItemDictionary
泛型類型,並發安全,可以為任何類型生成字典。通過運行genny
該代碼將創建一個特定於類型的Dictionary實現,並封裝實際的map
包含數據。
目標
該字典是使用以下方法創建的dict := ValueDictionary{}
並提供以下導出方法集:
Set()
Delete()
Has()
Get()
Clear()
Size()
Keys()
Values()
執行
// Package dictionary creates a ValueDictionary data structure for the Item type
package dictionary
import (
“sync”
<span style="color:#e6db74">"github.com/cheekybits/genny/generic"</span>
)
// Key the key of the dictionary
type Key generic.Type
// Value the content of the dictionary
type Value generic.Type
// ValueDictionary the set of Items
type ValueDictionary struct {
items map[Key]Value
lock sync.RWMutex
}
// Set adds a new item to the dictionary
func (d *ValueDictionary) Set(k Key, v Value) {
d.lock.Lock()
defer d.lock.Unlock()
if d.items == nil {
d.items = make(map[Key]Value)
}
d.items[k] = v
}
// Delete removes a value from the dictionary, given its key
func (d *ValueDictionary) Delete(k Key) bool {
d.lock.Lock()
defer d.lock.Unlock()
_, ok := d.items[k]
if ok {
delete(d.items, k)
}
return ok
}
// Has returns true if the key exists in the dictionary
func (d *ValueDictionary) Has(k Key) bool {
d.lock.RLock()
defer d.lock.RUnlock()
_, ok := d.items[k]
return ok
}
// Get returns the value associated with the key
func (d *ValueDictionary) Get(k Key) Value {
d.lock.RLock()
defer d.lock.RUnlock()
return d.items[k]
}
// Clear removes all the items from the dictionary
func (d *ValueDictionary) Clear() {
d.lock.Lock()
defer d.lock.Unlock()
d.items = make(map[Key]Value)
}
// Size returns the amount of elements in the dictionary
func (d *ValueDictionary) Size() int {
d.lock.RLock()
defer d.lock.RUnlock()
return len(d.items)
}
// Keys returns a slice of all the keys present
func (d *ValueDictionary) Keys() []Key {
d.lock.RLock()
defer d.lock.RUnlock()
keys := []Key{}
for i := range d.items {
keys = append(keys, i)
}
return keys
}
// Values returns a slice of all the values present
func (d *ValueDictionary) Values() []Value {
d.lock.RLock()
defer d.lock.RUnlock()
values := []Value{}
for i := range d.items {
values = append(values, d.items[i])
}
return values
}
測驗
這些測試描述了上述實現的用法。請注意,我們從不與基礎互動map
類型,如果只有Go尚未為我們提供地圖類型,則也可以通過其他方式實現。
package dictionary
import (
“fmt”
“testing”
)
func populateDictionary(count int, start int) *ValueDictionary {
dict := ValueDictionary{}
for i := start; i < (start + count); i++ {
dict.Set(fmt.Sprintf(“key%d”, i), fmt.Sprintf(“value%d”, i))
}
return &dict
}
func TestSet(t *testing.T) {
dict := populateDictionary(3, 0)
if size := dict.Size(); size != 3 {
t.Errorf(“wrong count, expected 3 and got %d”, size)
}
dict.Set(“key1”, “value1”) //should not add a new one, just change the existing one
if size := dict.Size(); size != 3 {
t.Errorf(“wrong count, expected 3 and got %d”, size)
}
dict.Set(“key4”, “value4”) //should add it
if size := dict.Size(); size != 4 {
t.Errorf(“wrong count, expected 4 and got %d”, size)
}
}
func TestDelete(t *testing.T) {
dict := populateDictionary(3, 0)
dict.Delete(“key2”)
if size := dict.Size(); size != 2 {
t.Errorf(“wrong count, expected 2 and got %d”, size)
}
}
func TestClear(t *testing.T) {
dict := populateDictionary(3, 0)
dict.Clear()
if size := dict.Size(); size != 0 {
t.Errorf(“wrong count, expected 0 and got %d”, size)
}
}
func TestHas(t *testing.T) {
dict := populateDictionary(3, 0)
has := dict.Has(“key2”)
if !has {
t.Errorf(“expected key2 to be there”)
}
dict.Delete(“key2”)
has = dict.Has(“key2”)
if has {
t.Errorf(“expected key2 to be removed”)
}
dict.Delete(“key1”)
has = dict.Has(“key1”)
if has {
t.Errorf(“expected key1 to be removed”)
}
}
func TestKeys(t *testing.T) {
dict := populateDictionary(3, 0)
items := dict.Keys()
if len(items) != 3 {
t.Errorf(“wrong count, expected 3 and got %d”, len(items))
}
dict = populateDictionary(520, 0)
items = dict.Keys()
if len(items) != 520 {
t.Errorf(“wrong count, expected 520 and got %d”, len(items))
}
}
func TestValues(t *testing.T) {
dict := populateDictionary(3, 0)
items := dict.Values()
if len(items) != 3 {
t.Errorf(“wrong count, expected 3 and got %d”, len(items))
}
dict = populateDictionary(520, 0)
items = dict.Values()
if len(items) != 520 {
t.Errorf(“wrong count, expected 520 and got %d”, len(items))
}
}
func TestSize(t *testing.T) {
dict := populateDictionary(3, 0)
items := dict.Values()
if len(items) != dict.Size() {
t.Errorf(“wrong count, expected %d and got %d”, dict.Size(), len(items))
}
dict = populateDictionary(0, 0)
items = dict.Values()
if len(items) != dict.Size() {
t.Errorf(“wrong count, expected %d and got %d”, dict.Size(), len(items))
}
dict = populateDictionary(10000, 0)
items = dict.Values()
if len(items) != dict.Size() {
t.Errorf(“wrong count, expected %d and got %d”, dict.Size(), len(items))
}
}
創建具體的字典數據結構
您可以使用以下通用實現來生成特定於類型的字典,方法是:
//generate a `IntDictionary` dictionary of `string` keys associated to `int` values
genny -in dictionary.go -out dictionary-string-int.go gen "Key=string Value=int"
//generate a </span>StringDictionary<span style="color:#e6db74">
dictionary of </span>string<span style="color:#e6db74">
keys associated to </span>string<span style="color:#e6db74">
values
genny -in dictionary.go -out dictionary-string-string.go gen “Key=string Value=string”
更多教程:
- 使用NGINX反向代理服務Go服務
- 在Go中復制結構
- Go Web服務器的基礎
- 在Go中對地圖類型進行排序
- 簡而言之去指針
- 轉到標籤說明
- 開始日期和時間格式
- 使用Go進行JSON處理
- 可變參數函數
- 去弦備忘單
- 轉到空界面說明
- 使用VS Code和Delve調試Go
- 命名為Go返回參數
- 在Go中生成隨機數和字符串
- Go項目的文件系統結構
- Go中的二進制搜索算法
- 在Go中使用命令行標誌
- GOPATH解釋
- 使用Go構建一個命令行應用程序:lolcat
- 使用Go構建CLI命令:Cowsay
- 在Go中使用殼管
- Go CLI教程:財富克隆
- 使用Go列出文件夾中的文件
- 使用Go從GitHub獲取存儲庫列表
- 去,將一小段字符串附加到文件中
- 去,將字符串轉換為字節片
- 使用Go可視化您本地的Git貢獻
- Go CPU和內存分析入門
- 解決Go程序中的“不支持索引”錯誤
- 測量Go程序中的執行時間
- 使用Go構建Web爬網程序以檢測重複的標題
- 最佳實踐:指針還是價值接收者?
- 最佳實踐:您應該使用方法還是函數?
- Go數據結構:集
- 前往地圖備忘單
- 在Go中生成泛型類型的實現
- Go數據結構:字典
- Go數據結構:哈希表
- 在“通過通道”中實現事件偵聽器
- Go數據結構:堆棧
- Go數據結構:隊列
- Go數據結構:二進制搜索樹
- Go數據結構:圖形
- Go數據結構:鍊錶
- Go數據結構的完整指南
- 比較Go值
- Go是面向對象的嗎?
- 在Go中使用SQL數據庫
- 在Go中使用環境變量
- 上篇教程:PostgreSQL支持的REST API
- 在Go Web服務器上啟用CORS
- 在Docker容器中部署Go應用程序
- 為什麼Go是作為PHP開發人員學習的功能強大的語言
- 去,刪除io.Reader.ReadString換行符
- 開始,如何觀看更改並重建程序
- 去算一下自約會以來的月份
- 在Go中訪問HTTP POST參數