go跳出多层循环的几种方式

摘要:
前言例如,需要遍历一个切片。切片的内容是切片1。需要判断切片1中是否有相应的数据,然后返回文本。我们需要考虑的是在编写两层遍历时如何完成两层遍历。variable方法用于设置变量,监听外层的变量,并修改变量funcmin(){t:=[][]int{1,2,3,4,5},{5,6,7,8,9}s:=false for _,v:=ranget{for_,v1:=range v{ifv1
前言

比如这样的需求, 遍历一个 切片, 切片内容是切片1, 需求是判断切片1中某个是否有相应数据, 有就返回

正文

我们需要考虑的是在写两层遍历时如何在获取结果后结束这两层遍历

变量法

设置一个变量, 在外层监听该变量, 获取到结果后修改该变量

func main() {
	t := [][]int{{1, 2, 3, 4, 5}, {5, 6, 7, 8, 9}}
	s := false
	for _, v := range t {
		for _, v1 := range v {
			if v1 == 5 {
				s = true // 判断成立修改标量退出二层循环
				break
			}
		}
		if s { // 检测标量结果,为true代表命中
			break
		}
	}
}

缺点很明显, 如果套更多层需要在每个层都写一个判断标量的逻辑一层层退出

goto

func main() {
	t := [][]int{{1, 2, 3, 4, 5}, {5, 6, 7, 8, 9}}
	for _, v := range t {
		for _, v1 := range v {
			if v1 == 5 {
				goto Loop // 跳转到注册名为Loop的标记处,中间的代码直接跳过
			}
		}
	}
	fmt.Println("nil")
	return // 此处return防止继续执行loop的代码
Loop: // Loop标记处, Loop只是一个标记,正常顺序执行也会执行Loop的代码,,一般叫Loop,可以自定义,与上面一致即可
	fmt.Println("success")
}

此方法不止适用于循环,实际上他可以贴在任意地方,比如

func main() {
	fmt.Println(1)
	goto Loop
	fmt.Println(2)
Loop:
	fmt.Println(3)
}

上面的 2 永远不会打印

这种方法的问题是会破坏正常的代码结构, 一个项目的代码必定是很多的, 有很多逻辑, 使用goto会破坏原有的代码结构, 大大降低了可读性和可维护性, 因此请尽可能的避免使用 goto

break Label

给某一层循环设置一个Label,指定跳过某一个Label

func main() {
	t := [][]int{{1, 2, 3, 4, 5}, {5, 6, 7, 8, 9}}
	s := false
Loop: // 标记该循环为Loop,一般叫Loop,可以自定义,与下面一致即可
	for _, v := range t {
		for _, v1 := range v {
			if v1 == 5 {
				s = true
				break Loop // 跳出Loop标记的循环
			}
		}
	}
	if s {
		fmt.Println("success")
	}
}

相比于 goto, break Label 只能在循环中使用, Loop只能注册到循环中, goto是跳转到某行执行, break是跳出Loop标记的循环,相对来说限制大一些, 没有那么随意, 而相比于 方法一,则无需写多层判断, 需要注意的是, break Label 的 Label 不一定是顶层, 可以在任意一层

func main() {
	t := [][][]int{{{1, 2, 3, 4, 5}}, {{5, 6, 7, 8, 9}}}
	s := false
	for _, v := range t {
	Loop: // 标记该循环为Loop
		for _, v1 := range v {
			for _, v2 := range v1 {
				if v2 == 5 {
					s = true
					break Loop // 跳出Loop标记的循环
				}
			}
		}
	}
	if s {
		fmt.Println("success")
	}
}

单独写一个函数

这个不多说, 因为 return 直接退出函数了

func t1(t [][][]int) bool {
	for _, v := range t {
		for _, v1 := range v {
			for _, v2 := range v1 {
				if v2 == 5 {
					return true
				}
			}
		}
	}
	return false
}

func main() {
	t := [][][]int{{{1, 2, 3, 4, 5}}, {{5, 6, 7, 8, 9}}}
	fmt.Println(t1(t))
}
总结

条条大路通罗马, 其实哪种都可以, 但是我还是推荐使用函数的形式, 因为goto和lable或多或少都会降低可读性. 何况, 如果真的出现多个循环在一个函数, 应该思考是不是设计的有问题或者实现的有问题.

免责声明:文章转载自《go跳出多层循环的几种方式》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【成语】咸鱼翻身史上最全最细 App 自动化环境部署下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Java的各类型数据在内存中分配情况详解

1.      有这样一种说法,如今争锋于IT战场的两大势力,MS一族偏重于底层实现,Java一族偏重于系统架构。说法根据无从考证,但从两大势力各自的社区力量和图书市场已有佳作不难看出,此说法不虚,但掌握Java的底层实现对Java程序员来说是至关重要的,本文介绍了Java中的数据在内存中的存储。      2 内存中的堆(stack)与栈(heap) ...

jmeter 逻辑控制器Logic Controller详解

Jmeter之逻辑控制器(Logic Controller) 前言: 1、 Jmeter官网对逻辑控制器的解释是:“Logic Controllers determine the order in which Samplers are processed.”。意思是说,逻辑控制器可以控制采样器(samplers)的执行顺序。由此可知,控制器需要和采样器一起...

PHP中的全局变量global和$GLOBALS的区别

1.global Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件。 但是在函数体内定义的global变量,函数体内可以使用,在函数体外定义的global变量不能在函数体内使用,具体看下面示例。 (1)在函数体内定义global变量,函数体内可以使用。 <?php...

jvm主内存与工作内存

一、jvm主内存与工作内存     首先,JVM将内存组织为主内存和工作内存两个部分。     主内存主要包括本地方法区和堆。每个线程都有一个工作内存,工作内存中主要包括两个部分,一个是属于该线程私有的栈和对主存部分变量拷贝的寄存器(包括程序计数器PC和cup工作的高速缓存区)。   1.所有的变量都存储在主内存中(虚拟机内存的一部分),对于所有线程都是共...

ROS(Robot Operating System)常用环境变量介绍

本文简单介绍ROS系统中常用的环境变量用途及设置方式。ROS系统环境中除了必须配置的环境变量以外,其他的也是十分有用,通过修改变量路径,可以设置ROS系统中log文件存放路径,单元测试结果存放路径等。 http://wiki.ros.org/ROS/EnvironmentVariables 一 、必选设置的环境变量 1、 ROS_ROOT 这个是ROS核心...

(转)Should 断言的基本使用方法

一、基础 RobotFramework带有丰富的系统关键,使用时无需导入,直接使用,为写自动化用例带来了极大的方便;不能停留在知道或者是会得程度,只有熟练使用各关键字,才能提升自动化用例的写作效率。下面将逐个举例介绍RobotFramework提供的断言关键字。 二、实例 为方便讲解,首先创建三个list变量:list_a、list_b、list_c;以及...