go语言中map学习
在 Go 语言中,map
是一种引用类型,这意味着它有以下特点:
-
内存结构:
map
实际上是一个指向底层数据结构的指针。这个底层数据结构包含键值对的集合。 -
赋值与传参: 当你给一个变量赋值一个
map
时,或者将map
作为函数参数传递时,实际上传递的是指针,而不是完整的数据结构副本。这意味着, 通过这种方式修改map
的内容,其他引用同一个map
的变量也能看到这些修改。 -
零值: 一个未初始化的
map
变量的零值是nil
。nil
map
不能用于存储键值对,需要使用make()
函数来创建一个可用的map
。 -
并发安全性: 由于
map
是引用类型,在并发访问时需要特别注意线程安全问题。多个goroutine同时读写同一个map
可能会导致数据竞争,需要使用互斥锁或者其他并发控制手段来保证线程安全
给出几个例子来说明 map
作为引用类型在赋值和传参时的行为:
- 赋值:
package main
import "fmt"
func main() {
// 创建一个 map
m1 := map[string]int{
"apple": 5,
"banana": 3,
}
// 赋值给 m2
m2 := m1
// 修改 m2 中的值
m2["apple"] = 10
// 打印 m1 和 m2
fmt.Println("m1:", m1)
fmt.Println("m2:", m2)
}
输出:
m1: map[apple:10 banana:3]
m2: map[apple:10 banana:3]
可以看到,当我们将 m1
赋值给 m2
时,m2
实际上是指向了与 m1
相同的底层 map 数据结构。所以当我们修改 m2
中的值时, m1
中的值也发生了变化。
- 函数传参:
package main
import "fmt"
func modifyMap(m map[string]int) {
m["apple"] = 10
}
func main() {
// 创建一个 map
m := map[string]int{
"apple": 5,
"banana": 3,
}
// 调用函数并打印 m
modifyMap(m)
fmt.Println("m:", m)
}
m: map[apple:10 banana:3]
在这个例子中,我们将 m
作为参数传递给 modifyMap
函数。由于 map
是引用类型,在函数内部对 m
的修改会反映到调用方的 m
上。
如果你不想在函数中改变原来的 m
变量,有以下两种方式可以处理:
- 复制一个新的 map:
package main import "fmt" func modifyMap(m map[string]int) { // 创建一个新的 map 并修改 newM := make(map[string]int, len(m)) for k, v := range m { newM[k] = v } newM["apple"] = 10 } func main() { // 创建一个 map m := map[string]int{ "apple": 5, "banana": 3, } // 调用函数并打印 m modifyMap(m) fmt.Println("m:", m) }
- 使用指针传参:
package main import "fmt" func modifyMap(m *map[string]int) { // 修改传入的 map 指针 (*m)["apple"] = 10 } func main() { // 创建一个 map m := map[string]int{ "apple": 5, "banana": 3, } // 调用函数并打印 m modifyMap(&m) fmt.Println("m:", m) }
m: map[apple:10 banana:3]
在这个例子中,我们将
m
的地址传递给modifyMap
函数,并在函数内部通过解引用的方式修改m
的值。这种方式也可以避免修改原m
变量。总之,关键是要理解
map
是引用类型,如果不想在函数中修改原map
变量,可以选择复制一个新的map
或者使用指针传参的方式。
原文地址:https://blog.csdn.net/u010565037/article/details/140639665
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!