C語言中文網 目錄
首頁 > Go語言教程 > Go語言接口 閱讀:1,813

Go語言使用空接口實現可以保存任意值的字典

空接口可以保存任何類型這個特性可以方便地用于容器的設計。下面例子使用 map 和 interface{} 實現了一個字典。字典在其他語言中的功能和 map 類似,可以將任意類型的值做成鍵值對保存,然后進行找回、遍歷操作。詳細實現過程請參考下面的代碼。
package main

import "fmt"

// 字典結構
type Dictionary struct {
    data map[interface{}]interface{} // 鍵值都為interface{}類型
}

// 根據鍵獲取值
func (d *Dictionary) Get(key interface{}) interface{} {
    return d.data[key]
}

// 設置鍵值
func (d *Dictionary) Set(key interface{}, value interface{}) {

    d.data[key] = value
}

// 遍歷所有的鍵值,如果回調返回值為false,停止遍歷
func (d *Dictionary) Visit(callback func(k, v interface{}) bool) {

    if callback == nil {
        return
    }

    for k, v := range d.data {
        if !callback(k, v) {
            return
        }
    }
}

// 清空所有的數據
func (d *Dictionary) Clear() {
    d.data = make(map[interface{}]interface{})
}

// 創建一個字典
func NewDictionary() *Dictionary {
    d := &Dictionary{}

    // 初始化map
    d.Clear()
    return d
}

func main() {

    // 創建字典實例
    dict := NewDictionary()

    // 添加游戲數據
    dict.Set("My Factory", 60)
    dict.Set("Terra Craft", 36)
    dict.Set("Don't Hungry", 24)

    // 獲取值及打印值
    favorite := dict.Get("Terra Craft")
    fmt.Println("favorite:", favorite)

    // 遍歷所有的字典元素
    dict.Visit(func(key, value interface{}) bool {

        // 將值轉為int類型,并判斷是否大于40
        if value.(int) > 40 {

            // 輸出很貴
            fmt.Println(key, "is expensive")
            return true
        }

        // 默認都是輸出很便宜
        fmt.Println(key, "is cheap")

        return true
    })
}

值設置和獲取

字典內部擁有一個 data 字段,其類型為 map。這個 map 的鍵和值都是 interface{} 類型,也就是實現任意類型關聯任意類型。字典的值設置和獲取通過 Set() 和 Get() 兩個方法來完成,參數都是 interface{}。詳細實現代碼如下:
// 字典結構
type Dictionary struct {
    data map[interface{}]interface{}  // 鍵值都為interface{}類型
}

// 根據鍵獲取值
func (d *Dictionary) Get(key interface{}) interface{} {
    return d.data[key]
}

// 設置鍵值
func (d *Dictionary) Set(key interface{}, value interface{}) {
    d.data[key] = value
}
代碼說明如下:
  • 第 3 行,Dictionary 的內部實現是一個鍵值均為 interface{} 類型的 map,map 也具備與 Dictionary 一致的功能。
  • 第 8 行,通過 map 直接獲取值,如果鍵不存在,將返回 nil。
  • 第 13 行,通過 map 設置鍵值。

遍歷字段的所有鍵值關聯數據

每個容器都有遍歷操作。遍歷時,需要提供一個回調返回需要遍歷的數據。為了方便在必要時終止遍歷操作,可以將回調的返回值設置為 bool 類型,外部邏輯在回調中不需要遍歷時直接返回 false 即可終止遍歷。

Dictionary 的 Visit() 方法需要傳入回調函數,回調函數的類型為 func(k,v interface{})bool。每次遍歷時獲得的鍵值關聯數據通過回調函數的 k 和 v 參數返回。Visit 的詳細實現請參考下面的代碼:
// 遍歷所有的鍵值, 如果回調返回值為false, 停止遍歷
func (d *Dictionary) Visit(callback func(k, v interface{}) bool) {

    if callback == nil {
        return
    }

    for k, v := range d.data {
        if !callback(k, v) {
            return
        }
    }
}
代碼說明如下:
  • 第 2 行,定義回調,類型為 func(k,v interface{})bool,意思是返回鍵值數據(k、v)。bool 表示遍歷流程控制,返回 true 時繼續遍歷,返回 false 時終止遍歷。
  • 第 4 行,當 callback 為空時,退出遍歷,避免后續代碼訪問空的 callback 而導致的崩潰。
  • 第 8 行,遍歷字典結構的 data 成員,也就是遍歷 map 的所有元素。
  • 第 9 行,根據 callback 的返回值,決定是否繼續遍歷。

初始化和清除

字典結構包含有 map,需要在創建 Dictionary 實例時初始化 map。這個過程通過 Dictionary 的 Clear() 方法完成。在 NewDictionary 中調用 Clear() 方法避免了 map 初始化過程的代碼重復問題。請參考下面的代碼:
// 清空所有的數據
func (d *Dictionary) Clear() {
    d.data = make(map[interface{}]interface{})
}

// 創建一個字典
func NewDictionary() *Dictionary {
    d := &Dictionary{}

    // 初始化map
    d.Clear()
    return d
}
代碼說明如下:
  • 第 3 行,map 沒有獨立的復位內部元素的操作,需要復位元素時,使用 make 創建新的實例。Go 語言的垃圾回收是并行的,不用擔心 map 清除的效率問題。
  • 第 7 行,實例化一個 Dictionary。
  • 第 11 行,在初始化時調用 Clear 進行 map 初始化操作。

使用字典

字典實現完成后,需要經過一個測試過程,查看這個字典是否存在問題。

將一些字符串和數值組合放入到字典中,然后再從字典中根據鍵查詢出對應的值,接著再遍歷一個字典中所有的元素。詳細實現過程請參考下面的代碼:
func main() {

    // 創建字典實例
    dict := NewDictionary()

    // 添加游戲數據
    dict.Set("My Factory", 60)
    dict.Set("Terra Craft", 36)
    dict.Set("Don't Hungry", 24)

    // 獲取值及打印值
    favorite := dict.Get("Terra Craft")
    fmt.Println("favorite:", favorite)

    // 遍歷所有的字典元素
    dict.Visit(func(key, value interface{}) bool {

        // 將值轉為int類型, 并判斷是否大于40
        if value.(int) > 40 {

            // 輸出“很貴”
            fmt.Println(key, "is expensive")
            return true
        }

        // 默認都是輸出“很便宜”
        fmt.Println(key, "is cheap")

        return true
    })
}
代碼說明如下:
  • 第 4 行創建字典的實例。
  • 第 7~9 行,將 3 組鍵值對通過字典的 Set() 方法設置到字典中。
  • 第 12 行,根據字符串鍵查找值,將結果保存在 favorite 中。
  • 第 13 行,打印 favorite 的值。
  • 第 16 行,遍歷字典的所有鍵值對。遍歷的返回數據通過回調提供,key 是鍵,value 是值。
  • 第 19 行,遍歷返回的 key 和 value 的類型都是 interface{},這里確認 value 只有 int 類型,所以將 value 轉換為 int 類型判斷是否大于 40。
  • 第 23 和 29 行,繼續遍歷,返回 true
  • 第 23 行,打印鍵。

運行代碼,輸出如下:
favorite: 36
My Factory is expensive
Terra Craft is cheap
Don't Hungry is cheap

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo