源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Go语言中的Array、Slice、Map和Set使用详解

  • 时间:2021-06-18 01:51 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Go语言中的Array、Slice、Map和Set使用详解
[b]Array(数组)[/b] [b]内部机制[/b] 在 Go 语言中数组是固定长度的数据类型,它包含相同类型的连续的元素,这些元素可以是内建类型,像数字和字符串,也可以是结构类型,元素可以通过唯一的索引值访问,从 0 开始。 数组是很有价值的数据结构,因为它的内存分配是连续的,内存连续意味着可是让它在 CPU 缓存中待更久,所以迭代数组和移动元素都会非常迅速。 [b]数组声明和初始化[/b] 通过指定数据类型和元素个数(数组长度)来声明数组。
[url=http://peter.bourgon.org/go-in-production/#formatting-and-style]为什么不使用make[/url])。初始化 map 的长度依赖于键值对的数量。 map 的键可以是任意内建类型或者是 struct 类型,map 的值可以是使用 ==操作符的表达式。slice,function 和 包含 slice 的 struct 类型不可以作为 map 的键,否则会编译错误:
[u]复制代码[/u] 代码如下:
dict := map[[]string]int{} Compiler Exception: invalid map key type []string
[b]使用 map[/b] 给 map 赋值就是指定合法类型的键,然后把值赋给键:
[u]复制代码[/u] 代码如下:
colors := map[string]string{} colors["Red"] = "#da1337"
如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对,否则会报运行时错误:
[u]复制代码[/u] 代码如下:
var colors map[string]string colors["Red"] = "#da1337" Runtime Error: panic: runtime error: assignment to entry in nil map
测试 map 的键是否存在是 map 操作的重要部分,因为它可以让我们判断是否可以执行一个操作,或者是往 map 里缓存一个值。它也可以被用来比较两个 map 的键值对是否匹配或者缺失。 从 map 里检索一个值有两种选择,我们可以同时检索值并且判断键是否存在:
[u]复制代码[/u] 代码如下:
value, exists := colors["Blue"] if exists {   fmt.Println(value) }
另一种选择是只返回值,然后判断是否是零值来确定键是否存在。但是只有你确定零值是非法值的时候这招才管用:
[u]复制代码[/u] 代码如下:
value := colors["Blue"] if value != "" {   fmt.Println(value) }
当索引一个 map 取值时它总是会返回一个值,即使键不存在。上面的例子就返回了对应类型的零值。 迭代一个 map 和迭代数组和 slice 是一样的,使用 range 关键字,不过在迭代 map 时我们不使用 index/value 而使用 key/value 结构:
[u]复制代码[/u] 代码如下:
colors := map[string]string{     "AliceBlue":   "#f0f8ff",     "Coral":       "#ff7F50",     "DarkGray":    "#a9a9a9",     "ForestGreen": "#228b22", } for key, value := range colors {   fmt.Printf("Key: %s  Value: %sn", key, value) }
如果我们想要从 map 中移除一个键值对,使用内建函数 delete(要是也能返回移除是否成功就好了,哎。。。):
[u]复制代码[/u] 代码如下:
delete(colors, "Coral") for key, value := range colors {   fmt.Println("Key: %s  Value: %sn", key, value) }
[b]在函数间传递 map[/b] 在函数间传递 map 不是传递 map 的拷贝。所以如果我们在函数中改变了 map,那么所有引用 map 的地方都会改变:
[u]复制代码[/u] 代码如下:
func main() {   colors := map[string]string{      "AliceBlue":   "#f0f8ff",      "Coral":       "#ff7F50",      "DarkGray":    "#a9a9a9",      "ForestGreen": "#228b22",   }   for key, value := range colors {       fmt.Printf("Key: %s  Value: %sn", key, value)   }   removeColor(colors, "Coral")   for key, value := range colors {       fmt.Printf("Key: %s  Value: %sn", key, value)   } } func removeColor(colors map[string]string, key string) {     delete(colors, key) }
执行会得到以下结果:
[u]复制代码[/u] 代码如下:
Key: AliceBlue Value: #F0F8FF Key: Coral Value: #FF7F50 Key: DarkGray Value: #A9A9A9 Key: ForestGreen Value: #228B22     Key: AliceBlue Value: #F0F8FF Key: DarkGray Value: #A9A9A9 Key: ForestGreen Value: #228B22
可以看出来传递 map 也是十分廉价的,类似 slice。 [b]Set[/b] Go 语言本身是不提供 set 的,但是我们可以自己实现它,下面就来试试:
[u]复制代码[/u] 代码如下:
package main import(   "fmt"   "sync" ) type Set struct {   m map[int]bool   sync.RWMutex } func New() *Set {   return &Set{     m: map[int]bool{},   } } func (s *Set) Add(item int) {   s.Lock()   defer s.Unlock()   s.m[item] = true } func (s *Set) Remove(item int) {   s.Lock()   s.Unlock()   delete(s.m, item) } func (s *Set) Has(item int) bool {   s.RLock()   defer s.RUnlock()   _, ok := s.m[item]   return ok } func (s *Set) Len() int {   return len(s.List()) } func (s *Set) Clear() {   s.Lock   defer s.Unlock()   s.m = map[int]bool{} } func (s *Set) IsEmpty() bool {   if s.Len() == 0 {     return true   }   return false } func (s *Set) List() []int {   s.RLock()   defer s.RUnlock()   list := []int{}   for item := range s.m {     list = append(list, item)   }   return list } func main() {   // 初始化   s := New()     s.Add(1)   s.Add(1)   s.Add(2)   s.Clear()   if s.IsEmpty() {     fmt.Println("0 item")   }     s.Add(1)   s.Add(2)   s.Add(3)     if s.Has(2) {     fmt.Println("2 does exist")   }     s.Remove(2)   s.Remove(3)   fmt.Println("list of all items", S.List()) }
注意我们只是使用了 int 作为键,你可以自己实现用 interface{} 作为键,做成更通用的 Set,另外,这个实现是线程安全的。 [b]总结[/b] 1.数组是 slice 和 map 的底层结构。 2.slice 是 Go 里面惯用的集合数据的方法,map 则是用来存储键值对。 3.内建函数 make 用来创建 slice 和 map,并且为它们指定长度和容量等等。slice 和 map 字面值也可以做同样的事。 4.slice 有容量的约束,不过可以通过内建函数 append 来增加元素。 5.map 没有容量一说,所以也没有任何增长限制。 6.内建函数 len 可以用来获得 slice 和 map 的长度。 7.内建函数 cap 只能作用在 slice 上。 8.可以通过组合方式来创建多维数组和 slice。map 的值可以是 slice 或者另一个 map。slice 不能作为 map 的键。 9.在函数之间传递 slice 和 map 是相当廉价的,因为他们不会传递底层数组的拷贝。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部