• 3.你所不知道的go语言控制语句——Leetcode习题69


    本篇前瞻

    好的,现在你已经来到一个新的小结,在这里你将学习到go语言的重要内容,习得go 25个关键字中的12个:var, const, if, else, switch, case, default, fallthrough, for, break, goto, continue,即在顺序结构学习var,const,在分支结构中学习if, else, switch, case, default, fallthrough,在循环结构中学习for, break, goto, continue。另外你最好注册一个Leetcode账号.

    Leetcode习题9

    让我们再来看下这个例子,这个是一个比较好的例子,里面包含了顺序,分支以及循环的所有控制结构

    题目描述

    9. 回文数

    给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false

    回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

    代码编写

    func isPalindrome(x int) bool {
    	if (x < 0) { //分支结构
    		return false
    	}
    	x64 := x   //顺序结构
    	px64 := 0
    	for x64 != 0 {  //循环结构
    		px64 = px64*10 + x64%10 // 顺序结构
    		x64 /= 10
    	}
    	return px64 == x 
    }
    

    你在这个道题目中能看到所有的控制结构:顺序结构,分支结构,循环机构

    控制结构

    顺序结构(Sequence)

    声明和赋值

    在顺序结构中声明和赋值是很重要的

    var可以声明一个变量,而const则声明一个常量

    package main
    
    import "fmt"
    
    func main() {
    	var i1 int     //声明变量,默认值为0
    	var i2 int = 1 //声明变量,初始化为1
    	i3 := 2        //这是最常用的声明和初始化手段
    	fmt.Println(i1, i2, i3)
    	i4 := i2 + i3 //使用运算表达式赋值
    	i3 *= i4      //使用运算表达式赋值
    	fmt.Println(i3, i4)
    	const ci1 int = 13 //声明常量,无法
    	fmt.Println(ci1)
    	x, y, z := 100, 101, 102 //多返回值
    	fmt.Println(x, y, z)     //打印结果
    }
    
    

    输出:

    0 1 2
    6 3
    13
    100 101 102
    

    这里仅仅举例了整形int的声明

    多返回值赋值

    x,y,z := 0,1,2
    

    go语言允许这样多返回值赋值赋值方式,再挖个坑,原因会在介绍函数时说明一下。

    运算符

    算术运算符

    ++ --
    自增1 自减1
    += -= *= /= %=
    自增 自减 自乘 自除 自模,取余
    + - * / %
    加法 减法 乘法 除法 模,取余

    注意: 例如如3/2 在整型中是整除即3/2=1,在浮点型是3.0/2.0=1.5,模运算智能用于整数

    位运算符

    << >> & | ^
    左移 右移 亦或
    <<= >>= &= |= ^=
    自左移 自右移 自与 自或 自亦或

    位运算符几乎我们这篇实用的编程用不到,但是这个概念也很重要,计算机底层事实上是这样工作的,这里在挖个坑,后面会介绍位运算的相关leetcode题目,你会看到它的威力。

    逻辑运算

    && || == !=
    相等 不等于
    >= <= > <
    大于等于 小于等于 大于 小于

    这些会在分支语句中大放异彩。

    分支结构

    if 语句

    if 语句有if,if-else以及if-else if-else结构,如下所示:

    package main
    
    import "fmt"
    
    func main() {
    	var input int
    	fmt.Printf("请输入分数:")
    	fmt.Scanf("%d", &input)
    	if input < 60 { //if
    		fmt.Println("1.不合格")
    	}
    
    	if input < 60 { //if-else
    		fmt.Println("2.不合格")
    	} else{
    		fmt.Println("2.合格")
    	}
    
    	if input < 60 {//if-else if-else
    		fmt.Println("3.不合格")
    	} else if input < 70 {
    		fmt.Println("3.合格")
    	} else if input < 85 {
    		fmt.Println("3.良好")
    	} else  {
    		fmt.Println("3.优秀")
    	}
    }
    

    结果如下:

    请输入分数:59
    1.不合格
    2.不合格
    3.不合格
    

    switch 语句

    事实上switch 语句比if语句更为强大,在有多个分支时更为符合go语言的风格,完整代码如下:

    package main
    
    import "fmt"
    
    func main() {
    	var i int
    	fmt.Printf("请输入分数:")
    	fmt.Scanf("%d\n", &i)
    	switch {
    	case i < 60: //单个逻辑表达式
    		fmt.Println("不合格")
    	case i < 70:
    		fmt.Println("合格")
    	case i < 85:
    		fmt.Println("良好")
    	default:
    		fmt.Println("优秀")
    	}
    
    	var c byte
    	fmt.Printf("请输入等级:")
    	fmt.Scanf("%c\n", &c)
    
    	switch c {
    	case 'E', 'e': //可以有多个选择
    		fmt.Println("1.不合格")
    	case 'D', 'd':
    		fmt.Println("1.基本合格")
    	case 'C', 'c':
    		fmt.Println("1.合格")
    	case 'B', 'b':
    		fmt.Println("1.良好")
    	case 'A', 'a':
    		fmt.Println("1.优秀")
    	default:
    		fmt.Println("1.错误的输入")
    	}
    
    	switch {
    	case c == 'E', c == 'e': //可以有多个表达式
    		fmt.Println("2.不合格")
    	case c == 'D', c == 'd':
    		fmt.Println("2.基本合格")
    	case c == 'C', c == 'c':
    		fmt.Println("2.合格")
    	case c == 'B', c == 'b':
    		fmt.Println("2.良好")
    	case c == 'A', c == 'a':
    		fmt.Println("2.优秀")
    	default:
    		fmt.Println("2.错误的输入")
    	}
    
    	switch {
    	case c == 'E':
    		fmt.Println("3.不合格")
    		fallthrough //fallthrough会执行下一个case区块
    	case c == 'e':
    		fmt.Println("3.真的不合格")
    	case c == 'D', c == 'd':
    		fmt.Println("3.基本合格")
    	case c == 'C', c == 'c':
    		fmt.Println("3.合格")
    	case c == 'B', c == 'b':
    		fmt.Println("3.良好")
    	case c == 'A', c == 'a':
    		fmt.Println("3.优秀")
    	default:
    		fmt.Println("3.错误的输入")
    	}
    
    	var in interface{} = i
    	switch data := in.(type) { //类型推断
    	case int:
    		fmt.Printf("int: %v\n", data)
    	case uint:
    		fmt.Printf("uint: %v\n", data)
    	default:
    		fmt.Printf("type: %T\n", data)
    	}
    }
    
    

    结果如下:

    请输入分数:90
    优秀
    请输入等级:E
    1.不合格
    2.不合格
    3.不合格
    3.真的不合格
    int: 90
    

    逻辑表达式

    注意case可以是单个或多个逻辑表达式

    	switch {
    	case c == 'E', c == 'e': //可以有多个表达式
    		fmt.Println("2.不合格")。
    	case c == 'D', c == 'd':
    		fmt.Println("2.基本合格")
    	case c == 'C', c == 'c':
    		fmt.Println("2.合格")
    	case c == 'B', c == 'b':
    		fmt.Println("2.良好")
    	case c == 'A', c == 'a':
    		fmt.Println("2.优秀")
    	default:
    		fmt.Println("2.错误的输入")
    	}
    

    fallthrough

    fallthrough会执行下一个case区块

    	switch {
    	case c == 'E':
    		fmt.Println("3.不合格")
    		fallthrough //fallthrough会执行下一个case区块
    	case c == 'e':
    		fmt.Println("3.真的不合格")
    	case c == 'D', c == 'd':
    		fmt.Println("3.基本合格")
    	case c == 'C', c == 'c':
    		fmt.Println("3.合格")
    	case c == 'B', c == 'b':
    		fmt.Println("3.良好")
    	case c == 'A', c == 'a':
    		fmt.Println("3.优秀")
    	default:
    		fmt.Println("3.错误的输入")
    	}
    

    类型推断

    这个是一个强大的方式,它可以用于推断go语言的接口的类型,不过现在只能简单那介绍一下,你可以将interface{}可以表达任何类型

    	var in interface{} = i
    	switch data := in.(type) { //类型推断
    	case int:
    		fmt.Printf("int: %v\n", data)
    	case uint:
    		fmt.Printf("uint: %v\n", data)
    	default:
    		fmt.Printf("type: %T\n", data)
    	}
    

    循环语句

    循环语句只有for

    package main
    
    import "fmt"
    
    func main() {
    	var input int
    	fmt.Printf("请输入分数(0-5):")
    	fmt.Scanf("%d", &input)
    
    	for i := 0; i < 5; i++ { //正常的for
    		fmt.Println("loop1:", i)
    
    		if i < 2 {
    			continue //跳过本次执行
    		}
    		if i == input {
    			fmt.Println("loop1: break") //跳出本层循环
    			break
    		}
    	}
    	i := 0
    Loop:
    	for i < 5 { //去掉;的for循环
    		fmt.Println("loop2:", i)
    		for j := 0; j < 5; j++ {
    			if j == input {
    				fmt.Println("loop2: break Loop") //跳出Loop标记的循环
    				break Loop
    			}
    			if j == 1 {
    				break //跳出本层循环
    			}
    		}
    		i++
    	}
    	i = 0
    	for ; i < 5; i++ { //空缺一个元素并带有;的for循环
    		fmt.Println("loop3:", i)
    		for j := 0; j < 5; j++ {
    			if j < 2 {
    				continue
    			}
    			if j == input {
    				goto Exit //跳出到Exit
    			}
    		}
    	}
    	return
    Exit:
    	fmt.Println("loop3: Exit")
    }
    

    结果如下:

    请输入分数(0-5):1
    loop1: 0
    loop1: 1
    loop1: 2
    loop1: 3
    loop1: 4
    loop2: 0
    loop2: break Loop
    loop3: 0
    loop3: 1
    loop3: 2
    loop3: 3
    loop3: 4
    
    请输入分数(0-5):2
    loop1: 0
    loop1: 1
    loop1: 2
    loop1: break
    loop2: 0
    loop2: 1
    loop2: 2
    loop2: 3
    loop2: 4
    loop3: 0
    loop3: Exit
    

    continue

    跳过本次循环

    break

    没有加标签的就是跳过本层循环

    加标签的就是跳过被标签标记的循环

    goto

    跳到被标签标记的循环,使用goto在处理一些同意的错误或者统一的出口而降低代码的冗余,增加代码可读性。这里挖个坑,这里会在go-etl展示goto的魅力

    注意:很多书籍指出goto会破环代码结构,降低代码可读性,那是因为这些书籍讲述使用goto的场景错了

    Leetcode习题69

    我们以leetcode习题开始,而现在有以一道Leetcode习题结束

    题目描述

    69. x 的平方根

    给你一个非负整数 x ,计算并返回 x算术平方根

    由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

    注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5

    题目分析

    这道题会比Leetcode习题1更加困难些,这次数据范围是int32的非负整数范围,由于不能使用指数函数和算符,为此,在这里我们需要使用二分法,即通过二分[a,b](mid = a + (b-a)/2, 第一轮a=0,b=x)去获取mid=x/2,如果mid*mid 那么此时二分[a,mid-1],反之二分[mid+1,b], 这样不断二分下去直到 mid*mid=x或者a。好的,这样我们获得了解题思路,但是还有个问题,选择y的数据类型是什么,如果选择int32,那么相乘必然超过int32, 为此我们必须选择int64,注意:在Leetcode习题9中得出了结论,int是64位的,所以不用改为int64

    代码编写

    func mySqrt(x int) int {
    	a, b := 0, x //多返回值赋值
    	for a <= b { // 无;结构的for
    		mid := a + (b-a)/2   //二分区间
    		if mid*mid == x { //if语句
    			return mid
    		}
    		if mid*mid < x { //if-else语句
    			a = mid + 1   //选择较大的区间
    		} else {
    			b = mid - 1  //选择较小的区间
    		}
    	}
    	return b
    }
    
    

    本篇小结

    恭喜你已经完成了所有控制结构的学习,你以及知道了所有控制结构用到的保留字和注意点。另外,通过Leetcode习题69和Leetcode习题9,你已经知道在编程时选择数据类型的重要性,并且练习了所有控制结构。这里的相关代码放在go语言学习的go-base/3中,请下载后进行实际的练习

    注意:之后的Leetcode题目解答以及使用工具的编程中,数据类型的选择以及控制结构的应用是非常重要的,也是最为基础的

    下篇预告

    go语言复合类型

  • 相关阅读:
    css常见居中方式
    JS逆向之行行查data解密
    做自媒体视频剪辑必备辅助工具分享
    Keras中model.evaluate() 返回的是 loss value 和 metrics values
    自监督学习系列(三):基于 Masked Image Modeling
    【Qt之QString】数值与进制字符串间的转换详解
    SAP Business Application Studio 里创建一个基于 CAP 模型的最简单的 OData 服务试读版
    浅谈微服务架构中实现单点登录
    【Make YOLO Great Again】YOLOv1-v7全系列大解析(Tricks篇)
    阿里巴巴2022届秋招面试真题和答案!
  • 原文地址:https://www.cnblogs.com/onlyac/p/17643470.html