一个网站的用户管理中,通常用户都会起一个昵称,固然用户A和用户B的昵称有可能相同,咱们就使用类型为map[string]int的集合来表示,其中string表明用户昵称、int表示昵称相同的人数。ide
集合数据内容为:{"chen":20, "chen长":10, "春风":5, "龙ge":13, "where你are":7}。学习
§问题1. 从这个集合中找出只包含中文的用户昵称的计数信息网站
上面集合中只有用户昵称为“春风”的元素知足条件,其它像“龙ge”、“chen长”、“where你are”都不是只包含中文。像看程序实现:spa
users := map[string]int{"chen": 20, "chen长": 10, "春风": 5, "龙ge": 13, "where你are": 7} var targetCount map[string]int = make(map[string]int) for name, count := range users { matched := true for _, v := range name { if v < '\u4e00' || v > '\u9fbf' { matched = false break } } if matched { targetCount[name] = count } } fmt.Println(targetCount)
解释一下:orm
第一层for循环遍历users集合,获得昵称(name)和计数(count ):字符串
for name, count := range users{get
// ......string
}it
第二层循环遍历昵称name字符串中的每一个字符,并判断是否有非中文字符:for循环
for _, v := range name{
if v <'\u4e00' || v > '\u9fbf' { // 该范围下的字符为非中文字符
}
}
【备注】:
这里由变量matched充当了标志,当出现非中文字符时,matched被赋为false,并使用break停止第二层循环,而后判断该name是否仅为中文,如果则添加进入targetCountw集合中。
运行结果为:map[春风:5]
§问题2. 从这个集合中找出只包含中文的用户昵称的计数信息,但发现第一个非全中文的用户昵称的时候就中止查找。
这里涉及到map类型的特性问题,当使用for进行遍历users集合时,顺序会出现不肯定性,即第一个昵称有多是“chen”,也有多是“春风”,也有多是“龙ge”,总之是不肯定的。
假设第一个昵称是“chen长”时,程序发现它是非全中文的昵称,这时整个程序须要结束。
for name, count := range users { matched := true for _, v := range name { if v < '\u4e00' || v > '\u9fbf' { matched = false break } } if !matched { break } else { targetCount[name] = count } } fmt.Println(targetCount)
这个程序实现与上面基本是大同小异,不一样之处在于第一层循环中的matched判断。
假设在第一层for循环中,第一次取到的昵称name为“龙ge”,此时第二层for循环中会逐个字符地查看“龙ge”这个字符串,当程序发现“龙ge”是非全中文时,matched标志被置为false,同时跑出第二层循环,而后在第一层循环中问:“取到的昵称‘龙ge’是否为全中文?”,结果不是,因而按照题目要求就break掉程序并时跳出第一层循环。
这里若是您多运行一下程序,就会发现结果有多是不一样的,有时为map[],有时为map[春风:5]
§问题3. 不使用辅助标识(如上例中的matched)解决§问题2.
做者这里是让您学习break Label这个东东,因此这里直接引用做者原话了:“咱们以前说过,break语句能够与标记(Label)语句一块儿配合使用。”
L: for name, count := range users { for _, v := range name { if v < '\u4e00' || v > '\u9fbf' { break L } } targetCount[name] = count }
该程序与§问题2程序功能是相同的,只是把标志matched移除掉了。
一条标记语句能够成为goto语句、break语句和contiune语句的目标。标记语句中的标记只是一个标识符,它能够被置在任何语句的左边以做为这个语句的标签。标记和被标记的语句之间须要用冒号“:”来分隔,即以下所示:
L:
for name, count := range users{
// .....
}
须要注意的是,标记L也是一个标识符,那么当它在未被使用的时候一样也会报告编译错误。那么怎么使用呢?一种方法就是让它成为break的目标,即上面示例中的break L。
标签L代码块包含了第一层for循环,第一层for循环包含了第二层for循环,因此当break L时,它是停止整个标签L代码块,因此这里会停止两层for循环。
对比“§问题2”和“§问题3”的两个代码实现,“§问题3”的代码更简洁一些。
§问题4. 仍是解决问题1的事情,只不过要求使用continue语句,即从这个集合中找出只包含中文的用户昵称的计数信息
因为这里没有更多的知识点,因此引用原文:
实际上,Go语言中的continue语句只能在for语句中使用。continue语句会使直接包含它的那个for循环直接进入下一次迭代,换言之,本次迭代不会执行该continue语句后面那些语句(它们被跳过了)。
for name, count := range users { matched := true for _, v := range name { if v < '\u4e00' || v > '\u9fbf' { matched = false break } } if !matched { continue } targetCount[name] = count }
或者
L: for name,count := range users{ for _, v := range name{ if r < '\u4e00' || r > '\u9fbf'{ continue L } } targetCount[name] = count }
OK,在读这个章节时,只是感受这个例子有点意思,因此分享给你们 :)