map,结构体

map的基本介绍

map是key-value数据结构,又称为字段或者关联数组。类似其它编程语言的集合。

map的声明

基本语法
var map变量名 map[keytype]valuetype
案例: var a map[string]int
map的声明是不会分配内存的,初始化需要make,分配内存后才能赋值和使用。
注意事项:
1)map在使用前一定要make。
2)map的key是不能重复,如果重复了,则以最后这个key-value为准。
3)map的value是可以相同的。
4)map的key-value是无序。
5)map内置函数数目 a =make(map[string]string,10)

//map使用的第一种方式
var  a  map[string]string
//在使用map前,需要先make(),make()的作用就是给map分配空间
a = make(map[string]string,10)
a["name1"] = "张三"
a["name2"] = "李四"
a["name3"] = "王五"

//map使用的第二种方式
cities  := make(map[string]string)
cities["city1"] = "北京"
cities["city2"] = "上海"
cities["city3"] = "武汉"

//map使用的第三种方式
heroes := map[string]string{
  "name1" : "张三",
   "name2" : "李四",
    "name3" : "王五",
}
heroes["name4"] = "马子"

map的增删改查操作

map增加和更新
//如果key还没有,就是增加,如果key存在就是修改
map[“key”] = value

map删除
delete(map,“key”) ,delete是一个内置函数,如果key存在,就删除该key-value,如果key不存在,不操作也不会报错。

//内建函数delete按照指定的键将元素从映射中删除。若m为nil或无此元素,delete不进行操作。
func delete(m map[Type]Type1, key Type)

如果我们要删除map的所有key,没有一个专门的方法一次删除,可以遍历一下key,来逐个删除 或map = make(…),make一个新的,让原来的成为垃圾,被gc回收。

map查询

val , ok :=cities["name1"]
if ok {
    fmt.Printf("存在name1 值为%v",val)
   }else {
    fmt.Printf("没有key为name1的值")
    }

map的使用注意事项和细节

1)map是引用类型,遵守引用类型传递的机制,在一个函数接受map,修改后会直接修改原来的map。
2)map的容量达到后,在想map增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长。
3)map是value也经常使用struct类型,更适合管理复杂的数据。

结构体

如何声明结构体

 type  结构体名称  struct{
     field1  type
     field2   type
 }
  type  Student  struct{
  Namr  string
  Age  int
  Score  float64
  }

创建结构体

type Person struct{
  Name  string
  Age  int
}
//方式1 直接声明
var  person  Person
person.Name = "marg"
person.Age = 20

//方式2
var person  Person =Person {"mary",20}

//方式3
// var  person * Person = new(Person)
var person *Person = new(Person)
//因为person是一个指针,因此标准的给字段赋值方式
// (*person).Name = "mary"  也可以这样写 person.Name = "mary"
//原因 :go的设计者 为了程序员使用方便 ,底层对 person.Name = "mary"进行了处理
// 会给person加上取值运算(*person).Name = "mary"
 (*person).Name = "mary"
  person.Name = "jack"

//方式4
//var person *Person = &Person{}
var person  *Person = &Person{"mary",20}  

说明:
1)第三种和第四种方式返回的是 结构体指针
2)结构体指针访问字段的标准方式应该是:(*结构体指针).字段名,比如(*person).Name = “tom”
3)但go设计者做了一个简化,也支持 结构体指针.字段名。go编译器底层对person.Name 做了转化(*person).Name

结构体使用主要事项和细节
1)结构体的所有字段在内存中是连续的
2)结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字,个数和类型)

type A struct {
  Num int
}

type B struct {
 Num int
}
fun main() {
   var a A
   var b B
   a = A(b)
}

3)结构体进行type重新定义(相等于取别名),Golang认为是新的数据类型,但是相互间可以强转
4) struct的每个字段上,可以写一个tag,该tag可以通过发射机制获取。

type Monster struct{
 Name  string  `json:"name"`
 Age  int  `json:"age"`
}
### Map 结构体的定义 在 Go 中,`map` 并不是一个真正的结构体,而是内置的数据类型之一。它的本质是一个哈希表(hash table),用于存储键值对(key-value pairs)。Map 的定义形式如下: ```go map[keyType]valueType ``` 其中 `keyType` 是键的类型,`valueType` 是值的类型。键必须是可以比较的类型(如整数、字符串、指针等),而值可以是任意类型。 关于 `map` 的具体实现细节,在底层是由运行时库管理的一个复杂数据结构完成的[^1]。Go 官方并未公开其实现的具体源码逻辑,但可以通过分析得知其内部采用了拉链法(chaining)处理冲突,并且动态调整容量以优化性能。 --- ### Map 的使用方法 #### 1. **创建** 可以通过字面量或者 `make` 函数创建一个 map: ```go m := make(map[string]int) n := map[string]string{"one": "uno", "two": "dos"} ``` #### 2. **赋值与访问** 通过键来设置或获取对应的值: ```go m["answer"] = 42 // 设置值 fmt.Println(m["answer"]) // 获取值 ``` 如果尝试访问不存在的键,则返回对应值类型的零值。例如对于 `int` 类型,默认会返回 `0`。 #### 3. **删除元素** 利用内置函数 `delete` 可移除指定键及其关联的值: ```go delete(m, "answer") // 删除 key "answer" ``` #### 4. **判断是否存在某键** 当不确定某个键是否存在时,可采用双变量的形式读取: ```go value, exists := m["answer"] if !exists { fmt.Println("Key does not exist.") } ``` 这里第二个返回值表明该键是否存在于映射中。 #### 5. **遍历** 借助 `for-range` 循环迭代所有的键值对: ```go for k, v := range n { fmt.Printf("%s -> %s\n", k, v) } ``` 以上操作均基于官方文档以及常见实践总结得出结论[^2]。 --- ### Map 的实现细节 尽管开发者无需关心太多底层机制即可高效运用 maps ,理解这些原理有助于编写更优代码 。以下是几个重要方面 : - **内存分配**: 初始状态下 , 当调用 `make()` 构造一个新的空闲状态下的 hash 表时候 , 如果未提供初始大小参数则默认初始化较小固定尺寸 . 随着不断插入新项目达到一定负载因子之后触发扩容过程 . - **扩容策略**: 扩展过程中并非简单复制原数组到更大空间里去 ; 而是对旧桶重新散列分布至新的两倍长度的新桶集合之中 . 此外为了减少一次性迁移带来的开销影响效率问题 , 整个转移动作被拆分成多次逐步完成 . 上述特性来源于标准库中的 runtime/map.go 文件解析结果[^3]. --- ### 示例代码展示如何自定义封装带接收者的 map 方法 虽然严格意义上讲 go 不允许直接为基本类型比如 slice 或者 map 添加额外行为方式像其他 oo 编程那样做继承之类的事情;但是我们仍然能够模仿这种模式设计辅助工具类来进行扩展功能演示: ```go package main import ( "fmt" ) // 自定义了一个包含 map 成员字段的结构体 type MyMap struct { data map[string]int } // 初始化构造器 func NewMyMap() *MyMap { return &MyMap{ data: make(map[string]int), } } // 提供 set 方法 func (mm *MyMap) Set(key string, value int) { mm.data[key] = value fmt.Printf("Inserted (%s:%d)\n", key, value) } // 提供 get 方法 func (mm *MyMap) Get(key string) (int, bool) { val, ok := mm.data[key] if !ok { fmt.Println("Not Found!") } else { fmt.Printf("Retrieved (%s:%d)\n", key, val) } return val, ok } func main() { myMap := NewMyMap() // 测试 insert 功能 myMap.Set("apple", 5) // 测试 retrieve 功能 num, found := myMap.Get("banana") if !found { fmt.Println("No bananas available.") } else { fmt.Println("Bananas count:", num) } } ``` 此例子展示了怎样把原始简单的 map 升级成具备更多特性的版本[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值