go语言基础(三):map、结构体

go语言基础(三):map、结构体

1. map

  • 语法:var map的名字 map[键类型]值类型 = make(map[键类型]值类型)
  • map的名字 := make(map[键类型]值类型)
    • 如果不写后面的make的话会报错

map在定义后不需要给它指定大小就能进行使用,和切片这一点不同要区分

对于map直接使用map名[键值]=数据值,就可以进行数据的添加

func main() {
	var m map[int]string = make(map[int]string)
	m[0] = "alin"
	m[1] = "linda"
	m[666] = "lili"
	// 每次打印时运行结果都不一样,原因:map的存储是无序的,所以只能使用范围遍历
	fmt.Println(m)

	// map的遍历
	// 范围遍历
	for k, v := range m {
		fmt.Println("key =", k, "value =", v)
	}
}
  • 注意:map的存储是无序的,所以在遍历的时候只能使用范围遍历

1.1 map的存储格式

链式存储,每一个map数据除了键和值以外还包括一个指向下一个元素的指针。

1.2 map的初始化和赋值

  • map的key必须支持== 和 !=操作, 不能支持函数、切片、map

  • 在初始化中键必须是唯一的,不能重复,如果写了重复的key会报错

  • map的名字就是它的首地址

  • map不能使用cap,只能使用len,求键值对的个数

func main01() {
	m := map[int]string{111: "alin", 222: "赵四", 333: "刘能"}
	fmt.Println(m)

	// 重置键对应的值
	m[222] = "广坤"
	fmt.Println(m)

	// 打印map中的值,通过key找value,不能通过key找到value
	fmt.Println(m[111])
}
func main() {
	m := map[int]string{101: "alin", 102: "刘能"}
	// map的名字就是一个map的地址
	fmt.Printf("%p\n", m)
	// 注意不能对map中的value取地址,value相当于是一个字面量,不能取地址
	// fmt.Printf("%p\n", &m[1])  // 报错

	// 打印长度
	fmt.Println(len(m))
}

小练习1:统计字符串中各个字符出现的次数

func main() {
	str := "hello world"
	m := make(map[byte]int)

	for i:=0; i<len(str); i++ {
		m[str[i]]++
	}
	for k, v := range m {
		fmt.Printf("%c:%d\n", k, v)
	}
}

小练习2:双色球

有红球和蓝球两种:红球数字在1-33,选择6个不允许重复;蓝球数字在1-16,只选一个

func main() {
	rand.Seed(time.Now().UnixNano())
	m := make(map[int]int)
	for len(m) != 6 {
		m[rand.Intn(33)+1] = 0
	}
	fmt.Print("红球:")
	for k, _ := range m {
		fmt.Print(k, " ")
	}
	fmt.Println()
	fmt.Println("蓝球:", rand.Intn(16)+1)
}

1.3 map中的键和值

map名[键值]这个可以把它理解为是一个函数调用类似,它有两个返回值,第一个是value,第二个是一个bool类型的值,表示是否存在对应这个键值的value。默认只使用一个返回值的话,是第一个值,忽略第二个值。

func main() {
	m := map[int]string{111: "alin", 222: "赵四", 333: "刘能"}
	value, ok := m[111]
	if ok {
		fmt.Println("value =", value)
	} else {
		fmt.Println("no this key")
	}

	fmt.Println(m[111])
}
  • map中的删除操作使用delete函数完成
    • 注意链式存储的删除会修改被删除项的前一项的指向
func main() {
	m := map[int]string{111: "alin", 222: "赵四", 333: "刘能"}
	fmt.Println(m)
	// 删除map中对应键值的元素,参1:map的名字,参2:要删除的key
	delete(m, 222)
	fmt.Println(m)
}

1.4 map做函数参数

map做函数参数是值传递,但是map名是一个地址,所以相当于了地址传递

func test(m map[int]string) {
	m[101] = "刘能"
	m[111] = "alin"
}

func main() {
	m := make(map[int]string)
	m[101] = "刘备"
	fmt.Println(m)
	// map名是一个地址,做了值传递后相当于传进去了map的地址,在函数内修改的也是这个map的内容
	test(m)
	fmt.Println(m)
}

2. 结构体

2.1 结构体的定义和赋值

语法:

type 结构体名 struct {
    成员1 成员数据类型
    成员2 成员数据类型
    ...
}
type student struct {
	name string
	id   int
	age  int
	sex  byte
}

func main() {
	// 结构体变量的定义和使用
	var stu student
	stu.name = "alin"
	stu.id = 29
	stu.age = 21
	stu.sex = 'm'
	fmt.Println(stu)

	s := student{"alin", 1, 21, 'm'}
	fmt.Println(s)

	fmt.Println(unsafe.Sizeof(stu.name))
	// 计算结构体的大小时,会发生内存对齐
	fmt.Println(unsafe.Sizeof(stu))

	s1 := s
	s.name = "lili"
	// 当发生结构体之间的赋值操作时,它是值传递,改变旧的值不会影响之前的
	fmt.Println(s)
	fmt.Println(s1)
}
// 结果
{alin 29 21 109}
{alin 1 21 109}
16
40
{lili 1 21 109}
{alin 1 21 109}

注意:在同一个包下结构体不能重名

2.2 结构体类型切片和数组

  • 结构体类型数组
type student1 struct {
	name string // 16
	id   int    // 8
	age  int    // 8
	sex  byte   // 1
}

func main() {
	// 定义结构体类型数组(数组和切片的区别就是在方括号中有指定大小)
	var arr [5]student1 = [5]student1{
		{"alin", 1001, 21, 'm'},
		{"lili", 1002, 22, 'f'},
		{"xiaoming", 1003, 23, 'm'},
		{"jiabao", 1004, 25, 'm'},
		{"yangshuai", 1005, 24, 'f'},   // 这里的逗号如果不写的话大括号要放到这行,不美观
	}
	//arr[0].name = "alin"
	//arr[0].id = 1001
	//arr[0].age = 21
	//arr[0].sex = 'm'
	fmt.Println(arr)
    
	fmt.Println(unsafe.Sizeof(arr))   // 200 结果是所有元素的占内存大小和
    fmt.Println(len(arr))   // 5 数组中的元素个数
}
  • 结构体类型切片
func main() {
	var slice []student1 = []student1{
		{"alin", 1001, 21, 'm'},
		{"lili", 1002, 22, 'f'},
		{"xiaoming", 1003, 23, 'm'},
		{"jiabao", 1004, 25, 'm'},
		{"yangshuai", 1005, 24, 'f'},   // 这里的逗号如果不写的话大括号要放到这行,不美观
	}
	slice = append(slice, student1{"yuepeng", 1006, 26, 'm'})
	fmt.Println(slice)

	fmt.Println(len(slice))     // 6
	fmt.Println(cap(slice))     // 10
}

注意:结构体类型变量是不能够进行大于小于等操作的,因为没有指定比较的方式无法进行比较,所以在比较的时候要指定成员变量的大小比较。

2.3 结构体变量做map的value

type student3 struct {
	name string // 16
	id   int    // 8
	age  int    // 8
	sex  byte   // 1
}

func main() {
	m := map[int]student3{1001:student3{"alin", 1001, 21, 'm'}}
	m[1002] = student3{"xiaoming", 18, 1002, 'm'}
	fmt.Println(m)
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值