最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Go中Set的實(shí)現(xiàn)方式

 更新時(shí)間:2019年09月16日 09:29:06   作者:LESS IS MORE  
這篇文章主要介紹了詳解Go中Set的實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

本篇主要講述如何利用Go語(yǔ)言的語(yǔ)法特性實(shí)現(xiàn)Set類型的數(shù)據(jù)結(jié)構(gòu)。

需求

對(duì)于Set類型的數(shù)據(jù)結(jié)構(gòu),其實(shí)本質(zhì)上跟List沒(méi)什么多大的區(qū)別。無(wú)非是Set不能含有重復(fù)的Item的特性,Set有初始化、Add、Clear、Remove、Contains等操作。接下來(lái)看具體的實(shí)現(xiàn)方式分析吧。

實(shí)現(xiàn)

仍然按照已有的編程經(jīng)驗(yàn)來(lái)聯(lián)想如何實(shí)現(xiàn)基本Set功能,在Java中很容易知道HashSet的底層實(shí)現(xiàn)是HashMap,核心的就是用一個(gè)常量來(lái)填充Map鍵值對(duì)中的Value選項(xiàng)。除此之外,重點(diǎn)關(guān)注Go中Map的數(shù)據(jù)結(jié)構(gòu),Key是不允許重復(fù)的,如下所示:

m := map[string]string{
 "1": "one",
 "2": "two",
 "1": "one",
 "3": "three",
 }
 fmt.Println(m)

程序會(huì)直接報(bào)錯(cuò),提示重復(fù)Key值,這樣就非常符合Set的特性需求了。

定義

前面分析出Set的Value為固定的值,用一個(gè)常量替代即可。但是筆者分析的實(shí)現(xiàn)源碼,用的是一個(gè)空結(jié)構(gòu)體來(lái)實(shí)現(xiàn)的,如下所示:

// 空結(jié)構(gòu)體
var Exists = struct{}{}
// Set is the main interface
type Set struct {
 // struct為結(jié)構(gòu)體類型的變量
 m map[interface{}]struct{}
}

為了解決上面為什么用空結(jié)構(gòu)體來(lái)做常量Value,先看下面的是測(cè)試:

import (
 "fmt"
 "unsafe"
)

// 定義非空結(jié)構(gòu)體
type S struct {
    a uint16
    b uint32
}

func main() {
 var s S
 fmt.Println(unsafe.Sizeof(s)) // prints 8, not 6
 var s2 struct{}
 fmt.Println(unsafe.Sizeof(s2)) // prints 0
}

打印出空結(jié)構(gòu)體變量的內(nèi)存占用大小為0,再看看下面這個(gè)測(cè)試:

a := struct{}{}
b := struct{}{}
fmt.Println(a == b) // true
fmt.Printf("%p, %p\n", &a, &b) // 0x55a988, 0x55a988

很有趣,a和b竟然相等,并且a和b的地址也是一樣的?,F(xiàn)在各位應(yīng)該明白了為什么會(huì)有:

var Exists = struct{}{}

這樣的常量也來(lái)填充所有Map的Value了吧,Go真是精彩?。?!

初始化

Set類型數(shù)據(jù)結(jié)構(gòu)的初始化操作,在聲明的同時(shí)可以選擇傳入或者不傳入進(jìn)去。聲明Map切片的時(shí)候,Key可以為任意類型的數(shù)據(jù),用空接口來(lái)實(shí)現(xiàn)即可。Value的話按照上面的分析,用空結(jié)構(gòu)體即可:

func New(items ...interface{}) *Set {
  // 獲取Set的地址
 s := &Set{}
 // 聲明map類型的數(shù)據(jù)結(jié)構(gòu)
 s.m = make(map[interface{}]struct{})
 s.Add(items...)
 return s
}

添加

簡(jiǎn)化操作可以添加不定個(gè)數(shù)的元素進(jìn)入到Set中,用變長(zhǎng)參數(shù)的特性來(lái)實(shí)現(xiàn)這個(gè)需求即可,因?yàn)镸ap不允許Key值相同,所以不必有排重操作。同時(shí)將Value數(shù)值指定為空結(jié)構(gòu)體類型。

func (s *Set) Add(items ...interface{}) error {
 for _, item := range items {
 s.m[item] = Exists
 }
 return nil
}

包含

Contains操作其實(shí)就是查詢操作,看看有沒(méi)有對(duì)應(yīng)的Item存在,可以利用Map的特性來(lái)實(shí)現(xiàn),但是由于不需要Value的數(shù)值,所以可以用 _,ok來(lái)達(dá)到目的:

func (s *Set) Contains(item interface{}) bool {
 _, ok := s.m[item]
 return ok
}

長(zhǎng)度和清除

獲取Set長(zhǎng)度很簡(jiǎn)單,只需要獲取底層實(shí)現(xiàn)的Map的長(zhǎng)度即可:

func (s *Set) Size() int {
 return len(s.m)
}

清除操作的話,可以通過(guò)重新初始化Set來(lái)實(shí)現(xiàn),如下即為實(shí)現(xiàn)過(guò)程:

func (s *Set) Clear() {
 s.m = make(map[interface{}]struct{})
}

相等

判斷兩個(gè)Set是否相等,可以通過(guò)循環(huán)遍歷來(lái)實(shí)現(xiàn),即將A中的每一個(gè)元素,查詢?cè)贐中是否存在,只要有一個(gè)不存在,A和B就不相等,實(shí)現(xiàn)方式如下所示:

func (s *Set) Equal(other *Set) bool {
 // 如果兩者Size不相等,就不用比較了
 if s.Size() != other.Size() {
 return false
 }
 
  // 迭代查詢遍歷
 for key := range s.m {
    // 只要有一個(gè)不存在就返回false
 if !other.Contains(key) {
  return false
 }
 }
 return true
}

子集

判斷A是不是B的子集,也是循環(huán)遍歷的過(guò)程,具體分析在上面已經(jīng)講述過(guò),實(shí)現(xiàn)方式如下所示:

func (s *Set) IsSubset(other *Set) bool {
 // s的size長(zhǎng)于other,不用說(shuō)了
 if s.Size() > other.Size() {
 return false
 }
  // 迭代遍歷
 for key := range s.m {
 if !other.Contains(key) {
  return false
 }
 }
 return true
}

Ok,以上就是Go中Set的主要函數(shù)實(shí)現(xiàn)方式,還是很有意思的。繼續(xù)加油。也希望大家多多支持腳本之家。

相關(guān)文章

  • GoLang職責(zé)鏈模式代碼實(shí)現(xiàn)介紹

    GoLang職責(zé)鏈模式代碼實(shí)現(xiàn)介紹

    這篇文章主要介紹了GoLang職責(zé)鏈模式代碼實(shí)現(xiàn),職責(zé)鏈模式是一種常用的設(shè)計(jì)模式,可以提高代碼的靈活性與可維護(hù)性,職責(zé)鏈模式將請(qǐng)求和處理分離,可以讓請(qǐng)求在處理鏈中依次經(jīng)過(guò)多個(gè)處理者,直到找到能夠處理請(qǐng)求的處理者為止
    2023-05-05
  • Go語(yǔ)言實(shí)現(xiàn)UDP版聊天小工具的示例詳解

    Go語(yǔ)言實(shí)現(xiàn)UDP版聊天小工具的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用Go語(yǔ)言實(shí)現(xiàn)聊天小工具(UDP版),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • go語(yǔ)言執(zhí)行windows下命令行的方法

    go語(yǔ)言執(zhí)行windows下命令行的方法

    這篇文章主要介紹了go語(yǔ)言執(zhí)行windows下命令行的方法,實(shí)例分析了Go語(yǔ)言操作windows下命令行的技巧,需要的朋友可以參考下
    2015-03-03
  • go語(yǔ)言發(fā)送smtp郵件的實(shí)現(xiàn)示例

    go語(yǔ)言發(fā)送smtp郵件的實(shí)現(xiàn)示例

    這篇文章主要介紹了go發(fā)送smtp郵件的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • GO語(yǔ)言包管理工具go?mod以及包詳解

    GO語(yǔ)言包管理工具go?mod以及包詳解

    go mod是go的一個(gè)模塊管理工具,用來(lái)代替?zhèn)鹘y(tǒng)的GOPATH方案,下面這篇文章主要給大家介紹了關(guān)于GO語(yǔ)言包管理工具go?mod以及包詳解的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • 基于Go語(yǔ)言簡(jiǎn)單實(shí)現(xiàn)事件管理器

    基于Go語(yǔ)言簡(jiǎn)單實(shí)現(xiàn)事件管理器

    在編程中,事件管理器是一種常見(jiàn)的工具,用于通過(guò)通知來(lái)觸發(fā)操作,本文將介紹一個(gè)簡(jiǎn)單的Go事件管理器的實(shí)現(xiàn),并通過(guò)異步改進(jìn)提高其性能,感興趣的可以了解下
    2023-11-11
  • go語(yǔ)言的工作空間和GOPATH環(huán)境變量介紹

    go語(yǔ)言的工作空間和GOPATH環(huán)境變量介紹

    這篇文章主要介紹了go語(yǔ)言的工作空間和GOPATH環(huán)境變量介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • Go 語(yǔ)言 IDE 中的 VSCode 配置使用教程

    Go 語(yǔ)言 IDE 中的 VSCode 配置使用教程

    Gogland 是 JetBrains 公司推出的Go語(yǔ)言集成開發(fā)環(huán)境。這篇文章主要介紹了Go 語(yǔ)言 IDE 中的 VSCode 配置使用教程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • golang?gorm學(xué)習(xí)之如何指定數(shù)據(jù)表

    golang?gorm學(xué)習(xí)之如何指定數(shù)據(jù)表

    在sql中首先要指定是從哪張表中查詢,所以這篇文章小編就來(lái)帶大家一起看一下gorm是如何根據(jù)model來(lái)自動(dòng)解析表名的,感興趣的小伙伴可以了解下
    2023-08-08
  • golang中l(wèi)og包自定義輸出日志格式與寫入到文件

    golang中l(wèi)og包自定義輸出日志格式與寫入到文件

    這篇文章主要給大家介紹了關(guān)于golang中l(wèi)og包自定義輸出日志格式與寫入到文件的相關(guān)資料,日志輸出在任何項(xiàng)目中都極其重要,是有助于后續(xù)我們排查解決程序BUG,需要的朋友可以參考下
    2023-06-06

最新評(píng)論

汾阳市| 邯郸市| 枝江市| 缙云县| 武宣县| 邵武市| 平塘县| 太和县| 凌云县| 大埔区| 婺源县| 滦平县| 商都县| 沾化县| 金平| 广平县| 建阳市| 鄄城县| 英山县| 永登县| 黑河市| 克什克腾旗| 吉木萨尔县| 马鞍山市| 威远县| 黔西| 峨边| 黄冈市| 郯城县| 盐亭县| 安福县| 桐城市| 沽源县| 罗城| 定南县| 河源市| 江阴市| 南丹县| 黔东| 东阿县| 定安县|