Golang基础之Map基础习题——李文周老师

本文通过实例分析了Golang中Map的基础使用,包括统计字符串中单词出现次数的功能,以及Map与切片交互时的内存行为。在处理字符串"how do you do?"时,展示了内置的Field方法的局限性。此外,文章深入探讨了一段代码中Map与切片的关系,当删除切片元素时,虽然它们共享同一底层数组,但切片的长度变化导致Map中的值与切片内容不同。通过对断点调试的观察,解释了这一现象的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 写一个程序,统计一个字符串中每个单词出现的次数。比如:”how do you do”中how=1 do=2 you=1。
代码如下:

package main

import (
	"fmt"
	"strings"
)

func main() {
	s := "how do you do"
	fmt.Println(WordCount(s))
}

func WordCount(s string) map[string]int {
	//return map[string]int{"x": 1}
	m := make(map[string]int) // map对象k是单词、v是单词出现个数
	c := strings.Fields(s)    // []byte
	for _, v := range c {
		m[v] += 1 //map中没有k,v就+1  有的话就增加一个v
	}
	return m
}

运行截图:
在这里插入图片描述
这里用到了内置的string包的Field方法来分隔单词,具体来讲,Field功能如下:
1. Fields 以连续的空白字符为分隔符,将 s 切分成多个子串,结果中不包含空白字符本身;
2. 空白字符有:\t, \n, \v, \f, \r, ’ ', U+0085 (NEL), U+00A0 (NBSP);
3. 如果 s 中只包含空白字符,则返回一个空列表。
由此看来,这种计词方法只能对一些简单的字符串起效,而如果遇上了"how do you do?",你就会发现“do?”也被计词一次。

2. 观察下面代码,写出最终的打印结果。

func main() {
	type Map map[string][]int
	m := make(Map)
	s := []int{1, 2}
	s = append(s, 3)
	fmt.Printf("%+v\n", s)
	m["q1mi"] = s
	s = append(s[:1], s[2:]...)
	fmt.Printf("%+v\n", s)
	fmt.Printf("%+v\n", m["q1mi"])
}

先上运行截图:
在这里插入图片描述
map[“q1mi”]的value竟然是[1 3 3],而且竟然是跟s的地址一样的情况下与s切片的内容不一样!
进行断点调试:
图一:
在这里插入图片描述
图二

看图分析,图一与我们的猜想是相符的——无论是两者的长度、容量还是其底层的数组都是完全一样的。到了图二,仔细看二者的不同之处,我在图中用不同颜色的框框标注的部分。红框框中的两个键值对的key由图一的红色变成了蓝色,是从图一到图二发生变化的部分。这样一看大家就能明白怎么回事儿了,原博客中讲到:
在这里插入图片描述
因此,s = append(s[:1], s[2:]...)其实就是删除切片中index为1的元素:2。由下图:在这里插入图片描述
再结合断点调试的图二可以得知,删除切片中的元素其实是把删除元素后面的元素向前一位复制一份,切片的长度len再减一,map[“q1mi”]与slice s指针指向的位置相同,但s长度的长度少1,所以会比map[“q1mi”]少一个元素3。
我移动s的右指针后证实了这个猜想。见下图:
在这里插入图片描述
map这节的第二题花费了我不少时间,询问了很多大佬也查了不少资料。最终的结果算是给了自己一个交待。作为初学者,寻根问底对后面知识的学习会有很大帮助,同时作为初学者的我也可能会出现纰漏,望大家能指出。
参考文章:go语言关于切片类型内存地址的理解
题目出处:[李文周Go基础之map基础]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值