详解Golang中哪些类型可以作为map的key

 更新时间:2024年01月11日 09:10:05   作者:路多辛  
在 Go 语言中,map 是一种内置的关联数据结构类型,由一组无序的键值对组成,每个键都是唯一的,并与一个对应的值相关联,本文将详细介绍哪些类型的变量可以作为 map 的键,并通过实例进行说明,感兴趣的朋友可以参考下

可以作为 map 键的类型

因为 map 需要能够判断两个键是否相等以确保每个键的唯一性,所以并非所有类型都可以作为 map 的键,可以作为 map 键的数据类型必须满足以下条件:

  • 可比较性(Comparable):用于定义 map 键的类型必须是可比较的,也就是说,Go 语言能够确定两个相同类型的键是否相等。这要求该类型支持 == 操作符来进行比较。
  • 不可变性(Immutable):虽然 Go 语言规范并未明确指出键必须不可变,但由于 map的内部实现机制,键在创建后不能改变,因此通常选择不可变类型作为键。

以下是可以作为 map 键的类型:

  • 基本类型,几乎所有的基本类型(整型、浮点型、字符串、布尔型等)都可以作为 map 的键,因为它们都支持相等性比较。
package main
 
import "fmt"
 
func main() {
	// 整数作为键
	mapInt := map[int]string{
		1: "one",
		2: "two",
		3: "three",
	}
  
	// 字符串作为键
	mapString := map[string]int{
		"Alice": 25,
		"Bob":   30,
		"Eve":   22,
	}
  
	// 浮点数作为键(不推荐,因为浮点数的比较可能会因精度问题导致不准确)
	mapFloat64 := map[float64]string{
		1.1: "one point one",
		2.2: "two point two",
		3.3: "three point three",
	}
 
	// 布尔值作为键
	mapBool := map[bool]string{
		true:  "true",
		false: "false",
	}
	fmt.Println(mapInt, mapString, mapFloat64, mapBool)
}
  • 指针类型,指针类型可以作为 map 的键,因为指针的比较是基于指向的内存地址的。简单示例代码如下:
package main
 
import "fmt"
 
func main() {
    type Person struct {
       Name string
       Age  int
    }
 
    alice := &Person{"Alice", 25}
    bob := &Person{"Bob", 30}
 
    mapPointer := map[*Person]string{
       alice: "Alice's pointer",
       bob:   "Bob's pointer",
    }
    fmt.Println(mapPointer)
}
  • 接口类型,接口类型可以作为 map 的键,只要接口的动态类型(即实际存储的类型)是可比较的。简单示例代码如下:
package main
 
import "fmt"
 
type Equalizer interface {
    Equal(Equalizer) bool
}
 
type IntEqualizer int
 
func (i IntEqualizer) Equal(e Equalizer) bool {
    other, ok := e.(IntEqualizer)
    return ok && i == other
}
 
func main() {
    mapInterface := map[Equalizer]string{
       IntEqualizer(1): "one",
       IntEqualizer(2): "two",
       IntEqualizer(3): "three",
    }
    fmt.Println(mapInterface)
}
  • 结构体类型,结构体类型可以作为 map 的键,只要其所有字段都是可比较的。简单示例代码如下:
package main
 
import "fmt"
 
func main() {
    type Point struct {
       X, Y int
    }
 
    mapStruct := map[Point]string{
       {1, 2}: "Point at (1,2)",
       {3, 4}: "Point at (3,4)",
    }
    fmt.Println(mapStruct)
}
  • 数组类型,数组类型可以作为 map 的键,只要数组中的元素类型是可比较的。简单示例代码如下:
package main
 
import "fmt"
 
func main() {
    arr1 := [3]int{1, 2, 3}
    arr2 := [3]int{4, 5, 6}
    mapArray := map[[3]int]string{
       arr1: "123",
       arr2: "456",
    }
    fmt.Println(mapArray)
}

不能作为 map 键的类型

以下类型不能作为 map 的键:

  • 切片类型,因为切片是引用类型,其内容可能会变化,使得比较操作不确定。
  • 函数类型,因为 Go 语言中没有为函数定义相等性比较操作。
  • map 类型,map 类型不能作为 map 的键,因为也是引用类型,且没有定义相等性比较操作。
  • 包含上述不可比较类型的复合类型,任何包含上述不可比较类型(如切片、函数、映射)的复合类型,如结构体,也不能作为 map 的键。

最佳实践

  • 使用不可变类型作为键,map 的键必须是可比较的类型,可以使用任何内置的可比较类型,如 int、string、float 等。
  • 如果键是自定义类型,需要使该类型必须支持 == 和 != 比较运算。
  • 如果使用结构体作为键,需要保证结构体的字段不会被修改。如果结构体的字段发生变化,可能会导致无法找到键值对。
  • 虽然指针可以作为键,但是两个相同内容的不同指针会被视为不同的键。
  • 字符串作为键时,尤其是在有大量独特字符串时,可能会导致内存使用的增加。这种情况下,可以考虑使用字符串的哈希值作为键,但要注意潜在的散列冲突。
  • 最小化键的大小,更小的键可以减少内存的占用,同时可以提高查找的效率。

小结

在 Go 语言中,只有那些不可变并且可比较的类型才能作为 map 的键。在日常编程中,应该选择合适的键类型以确保 map 的高效和准确性。

以上就是详解Golang中哪些类型可以作为map的key的详细内容,更多关于Golang作为map的key的类型的资料请关注脚本之家其它相关文章!

相关文章

  • Golang搭建HTTP服务器

    Golang搭建HTTP服务器

    Golang是一种非常流行的编程语言,它的开发速度快,代码运行效率高等特点非常适合做Web应用的开发。本文将介绍如何使用Golang搭建HTTP服务器,需要的朋友可以参考阅读
    2023-04-04
  • go GCM gin中间件的加密解密文件流处理

    go GCM gin中间件的加密解密文件流处理

    这篇文章主要介绍了go语言 GCM加密解密,gin中间件的加密解密及文件流处理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2022-05-05
  • go语言实现简单http服务的方法

    go语言实现简单http服务的方法

    这篇文章主要介绍了go语言实现简单http服务的方法,涉及Go语言http操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • 详解Go语言中Get/Post请求测试

    详解Go语言中Get/Post请求测试

    这篇文章主要为大家详细介绍了Go语言中的环境安装以及Get和Post请求接口的测试,文中的示例代码讲解详细,感兴趣的可以跟随小编一起学习一下
    2022-06-06
  • golang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • Go语言底层原理互斥锁的实现原理

    Go语言底层原理互斥锁的实现原理

    这篇文章主要介绍了Go语言底层原理互斥锁的实现原理,Go sync包提供了两种锁类型,分别是互斥锁sync.Mutex和读写互斥锁sync.RWMutex,都属于悲观锁,更多相关内容需要的朋友可以查看下面文章内容
    2022-08-08
  • gorm整合进go-zero的实现方法

    gorm整合进go-zero的实现方法

    go-zero提供的代码生成器里面,没有提供orm框架操作,但是提供了遍历的缓存操作,所以可以利用gorm当作一个sql语句的生成器,把生成后的sql语句放到go-zero生成的模板中去执行,对gorm整合进go-zero的实现方法感兴趣的朋友一起看看吧
    2022-03-03
  • Golang http请求封装的代码示例

    Golang http请求封装的代码示例

    http请求封装在项目中非常普遍,下面笔者封装了http post请求传json、form 和get请求,以备将来使用,文中代码示例介绍的非常详细,需要的朋友可以参考下
    2023-06-06
  • 教你一分钟配置好Go语言开发环境(多种操作系统)

    教你一分钟配置好Go语言开发环境(多种操作系统)

    在这篇文章中,我们从头到尾一步步指导你配置Golang开发环境,并编写你的第一个"Hello, World!"程序,我们详细解释了在多种操作系统(包括Windows、Linux和macOS)下的安装过程、环境变量设置以及如何验证安装是否成功
    2023-09-09
  • 浅析Golang开发中goroutine的正确使用姿势

    浅析Golang开发中goroutine的正确使用姿势

    很多初级的Gopher在学习了goroutine之后,在项目中其实使用率不高,所以这篇文章小编主要来带大家深入了解一下goroutine的常见使用方法,希望对大家有所帮助
    2024-03-03

最新评论