GO语言基础条件、跳转、Array和Slice
1. 判断语句if
1. 条件表达式没有括号(这点其他语言转过来的需要注意)
2. 支持一个初始化表达式(可以是并行方式,即:a, b, c := 1, 2, 3)
3. 左大括号必须和条件语句或 else 在同一行
4. 支持单行模式
5. 初始化语句中的变量为 block 级别,同时隐藏外部同名变量
有关 if 语句示例代码如下:
package main import "fmt" func main() {
a := true
if a, b, c := 1, 2, 3; a + b + c > 6 {
fmt.Println("大于6")
} else {
fmt.Println("小于等于6")
fmt.Println(a)
}
fmt.Println(a)
if 7 % 2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
}
运行打印结果如下所示:
1
2
3
|
小于等于6 1 true <br>7 is odd |
if 判断语句比较简单,只要掌握了相关的语法结构以及上一节讲到的相关基础知识,应用 if 语句也就没有什么问题了。
2. 循环语句 for
1. Go 只有 for 一个循环语句关键字,但是它支持3中形式
2. 初始化和步进表达式可以是多个值
3. 条件语句每次循环都会被重新检查,因此不建议在条件语句中使用函数,尽量提前计算好条件并以变量或常量代替
4. 左大括号必须和条件语句在同一行
package main import (
std "fmt"
) func main() {
/**
以下演示for的3种表现形式
*/
i := 1
for i <= 3 { // 类似于java中的:while(i <= 3){}
std.Println(i)
i = i + 1
} for { // 类似于java中的:while(true){}
std.Println("while loop")
break
} for n := 0; n <= 5; n++ { // 类似于java中的:for (int n = 0; n <= 5; n++) {}
if n % 2 == 0 {
continue
}
std.Println(n)
}
}
以上代码打印结果如下所示:
1
2
3
4
5
6
7
|
1 2 3 while loop 1 3 5 |
3. 选择语句 switch
1. 可以使用任何类型或表达式作为条件语句
2. 不需要写break,一旦条件符合自动终止
3. 如果希望继续执行下一个case,需使用 fallthrough 语句
4. 支持一个初始化表达式(可以是并行方式),右侧需要跟分号,和 if 条件表达式一样
5. 左大括号必须和条件语句在同一行
1 package main
2
3 import (
4 std "fmt"
5 "time"
6 )
7
8 func main() {
9 i := 2
10 std.Println("Write number ", i, " as ")
11 switch i { // 基本switch使用
12 case 1:
13 std.Println("one")
14 case 2:
15 std.Println("two")
16 case 3:
17 std.Println("three")
18 default:
19 std.Println("ohter")
20 }
21
22 switch time.Now().Weekday() { // 条件表达式作为判断条件
23 case time.Saturday, time.Sunday:
24 std.Println("It's the weekend")
25 default:
26 std.Println("It's a weekday")
27 }
28
29 t := time.Now()
30 switch { // 没有判断语句则和 if/else 效果一样
31 case t.Hour() < 12:
32 std.Println("It's before noon")
33 default:
34 std.Println("It's after noon")
35 }
36
37 a := 1
38 switch {
39 case a >= 0:
40 std.Println("a >= 0")
41 fallthrough // 这里不加的话,只会打印 a >= 0,不会向下执行了
42 case a >= 1:
43 std.Println("a >= 1")
44 }
45 }
以上代码运行结果如下:
1
2
3
4
5
6
|
Write number 2 as two It's a weekday It's after noon a >= 0 a >= 1 |
4. 跳转语句 goto、break、continue
1. 三个语法都可以配合标签使用
2. 标签名区分大小写,若不使用会造成编译错误
3. break 与 continue 配合标签可用于多层循环的跳出
4. goto 是调整执行位置,与其他 2 个语句配合标签的结果并不相同
1 package main
2
3 import std "fmt"
4
5 func main() {
6 LABEL_BREAK:
7 for {
8 for i := 0; i < 10; i++ {
9 if i > 2 {
10 break LABEL_BREAK // 结束循环到指定目标位置
11 } else {
12 std.Println("break number is : ", i)
13 }
14 }
15 }
16
17 LABEL_CONTINUE:
18 for i := 0; i < 10; i++ {
19 for {
20 std.Println(i)
21 continue LABEL_CONTINUE // 结束当前循环层到指定目标位置重新开始
22 }
23 }
24
25 // LABEL_GOTO 如果goto跳转目标放在这里,则形成了死循环
26 for {
27 for i := 0; i < 10; i++ {
28 if i > 2 {
29 goto LABEL_GOTO // 跳转到指定目标,从指定目标后开始继续执行
30 } else {
31 std.Println("goto number is : ", i)
32 }
33 }
34 }
35 LABEL_GOTO:
36 }
以上代码打印结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
break number is : 0 break number is : 1 break number is : 2 0 1 2 3 4 5 6 7 8 9 goto number is : 0 goto number is : 1 goto number is : 2 |
5. 数组 Array
1. 定义数组的格式:var name [num]type --> var a [10]int (定义1个长度为10类型为int的数组,数组名为 a)
2. 数组长度也是类型的一部分,因此具有不同长度的数组为不同的类型,这点很重要
3. 数组再 Go 中为值类型,故数组之间可以使用 ==、!= 进行比较,但不可以使用 <、> 进行判断
4. 可以使用 new 来创建数组,此方法返回一个指向数组的指针
5. Go 支持多维数组,但是就和其他语言一样,不推荐使用
针对数组的基本应用案例如下:
package main import "fmt" func main() {
var a [5]int // 以为数组的基本应用
fmt.Println("emp:", a) a[4] = 100
fmt.Println("set:", a)
fmt.Println("get:", a[4]) fmt.Println("len:", len(a)) b := [5]int{1, 2, 3, 4, 5} // 数组初始化并赋值
fmt.Println("arrayB:", b) var twoD [2][3]int // 二维数组的应用
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("twoD:", twoD)
}
以上代码打印结果如下所示:
1
2
3
4
5
6
|
emp: [0 0 0 0 0] set: [0 0 0 0 100] get: 100 len: 5 arrayB: [1 2 3 4 5] twoD: [[0 1 2] [1 2 3]] |
那么,这里使用数组采用冒泡排序方式实现对一组数排序功能,代码如下:
package main import (
"fmt"
) func main() {
// 未排序数组,此处使用的变长数组其长度决定于你传入数据的多少
sort := [...]int{1, 7, 4, 2, 5}
fmt.Println(sort) // 冒泡排序,由大到小
num := len(sort)
for i := 0; i < num; i++ {
for j := i + 1; j < num; j++ {
// 比较大小
if sort[i] < sort[j] {
temp := sort[i]
sort[i] = sort[j]
sort[j] = temp
}
}
} fmt.Println(sort)
}
以上代码运行结果如下所示:
1
|
[9 7 4 3 2] |
6. 切片 Slice
1. 其本身并不是数组,它指向底层的数组
2. 作为变长数组的替代方案,可以关联底层数组的局部或全部
3. slice 类型为引用类型
4. 可以直接创建或从底层数组获取生存
5. 使用 len() 获取元素个数,cap() 获取容量
6. 一般使用 make() 创建
7. 如果多个 slice 指向相同底层数组,其中一个的值改变会影响全部
8. make([]T, len, cap) 其中 cap 可以省略,则和 len 的值相同,len 表示元素的个数,cap 表示当前最大可以存放的容量
1 package main
2
3 import "fmt"
4
5 func main() {
6 // 创建长度为3,容量为3的切片,容量不设置默认为与len相同
7 s := make([]string, 3)
8 fmt.Println(s)
9
10 // 通过操作切片对数组进行赋值
11 s[0] = "a"
12 s[1] = "b"
13 s[2] = "c"
14 fmt.Println("set:", s)
15 fmt.Println("get:", s[2])
16
17 fmt.Println("len:", len(s), ", cap:", cap(s))
18
19 // 创建长度为3容量为10类型为int对切片,当放置元素超过10底层会自动翻倍到容量为20,再超再翻倍为49,如此类推
20 s1 := make([]int, 3, 10)
21 fmt.Println("len:", len(s1), ", cap:", cap(s1))
22
23 s1 = append(s1, 9, 7, 5)
24 fmt.Println("append:", s1)
25 fmt.Println("len:", len(s1), ", cap:", cap(s1))
26
27 // 实现切片等拷贝
28 c := make([]int, len(s1))
29 copy(c, s1)
30 fmt.Println("copy:", c)
31
32 // 实现切片上等再切片,类似与python中等截取
33 l := s1[2:5] // 范围为:[2, 5) 即前闭后开
34 fmt.Println("slice[2:5]:", l)
35
36 l = s1[:5] // 范围为:[0, 5)
37 fmt.Println("slice[:5]:", l)
38
39 l = s1[2:] // 范围为:[2, len(s1))
40 fmt.Println("slice[2:]:", l)
41
42 // 也可以初始化切片时直接赋初始值
43 t := []string{"a", "b", "g", "h", "l"}
44 fmt.Println("init slice:", t)
45
46 // 切片还可以存放不同长度等组合
47 twoD := make([][]int, 3)
48 for i := 0; i < 3; i++ {
49 innerLen := i + 1
50 twoD[i] = make([]int, innerLen)
51 // 为内部数据进行赋值
52 for j := 0; j < innerLen; j++ {
53 twoD[i][j] = i + j
54 }
55 }
56 fmt.Println("towD:", twoD)
57 }
以上代码运行结果如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[ ] set: [a b c] get: c len: 3 , cap: 3 len: 3 , cap: 10 append: [0 0 0 9 7 5] len: 6 , cap: 10 copy : [0 0 0 9 7 5] slice[2:5]: [0 9 7] slice[:5]: [0 0 0 9 7] slice[2:]: [0 9 7 5] init slice: [a b g h l] towD: [[0] [1 2] [2 3 4]] |
以上切片代码,其实可以用下面这张图片解释 Slice 与底层数组的对应关系:
切片概念很重要,对后续很多程序都有很大的用处,这里真对切片中几个重要的概念再着重提一下:
reslice(如上图中的 Slice_a 和 Slice_b)
1. reslice 时索引以被 slice 的切片为准
2. 索引不可以超过被 slice 的切片的容量 cap() 值
3. 索引越界不会导致底层数组的重新分配而是引发错误
说明:这里说的 reslice 代表当前切片是基于数组或 slice 截取生成的,即是它们其中的一部分
append
1. 可以在 slice 尾部增加元素
2. 可以将一个 slice 追加在另外一个 slice 尾部
3. 如果最终长度未超过追加到 slice 的容量则返回原是 slice
4. 如果超过追加到的 slice 的容量则将重新分配数组并拷贝原始数据
copy
1. coyp(dest, source) 两个参数代表将第二个参数代表的切片拷贝给第一个参数代表的切片
小总结:Array 与 Slice 之间的区别
数组Array所有使用案例如下:
var m [3]int // 定义了一个长度为3的int数组,元素值都为0 m:= [3]int{} // 声明了一个长度为3的int数组,元素值都为0 a := [3]int{1, 2, 3} // 声明了一个长度为3的int数组 b := [10]int{1, 2, 3} // 声明了一个长度为10的int数组,其中前三个元素初始化为1、2、3,其它默认为0 c := [...]int{4, 5, 6} // 可以省略长度而采用 "..." 的方式,Go会自动根据元素个数来计算长度 |
切片Slice所有使用案例如下:
var m []int // 声明了一个指向底层数组的切片 m:= []int{} // 声明了一个指向底层数组的切片 a := array[2:5] // a指向数组的第3个元素开始,并到第五个元素结束的切片 b := array[:5] // b指向数组的第0个元素开始,并到第五个元素结束的切片 c := array[2:] // c指向数组的第2个元素开始,并到最后一个元素结束的切片 d := b[3:] // d指向切片的第3个元素开始,并到最后一个元素结束的切片(即可以切片嵌套) |
由上面的结果可以看出,声明数组时,方括号内写明了数组的长度或使用...自动计算长度,而声明 slice时,方括号内没有任何字符。
GO语言基础条件、跳转、Array和Slice的更多相关文章
- GO_04:GO语言基础条件、跳转、Array和Slice
1. 判断语句if 1. 条件表达式没有括号(这点其他语言转过来的需要注意) 2. 支持一个初始化表达式(可以是并行方式,即:a, b, c := 1, 2, 3) 3. 左大括号必须和条件语句或 e ...
- day04<Java语言基础+>
Java语言基础(循环结构概述和for语句的格式及其使用) Java语言基础(循环结构for语句的练习之获取数据) Java语言基础(循环结构for语句的练习之求和思想) Java语言基础(循环结构f ...
- C语言基础(转载自大海笔记)
# C语言基础2015年03月26日10:04:411. 语言排行榜C——java——objective-C2. 进制:进制:进位机制.用普通的话讲,应该为人为的定义一种度量来标识一样东西 ...
- JavaScript 语言基础
js语言基础 一 基本知识 UniCode编码 区分大小写(HTML不区分/XHTML区分) Unicode转义序列 \uxxxx (\u加4位16进制表示) 注释 单行注释:// 多行注释:/* * ...
- Go语言基础知识总结(持续中)
Go基础知识总结 变量声明 Go语言中的变量需要声明以后才可以使用(需要提前定义变量)并且声明后必须使用(不适用会报错) 标准声明 var 变量名 变量类型 example: var name str ...
- Object Pascal 语言基础
Delphi 是以Object Pascal 语言为基础的可视化开发工具,所以要学好Delphi,首先要掌握的就是Object Pascal 语言.Object Pascal语言是Pascal之父在1 ...
- 01_C语言基础
内容提要: 1. C语言概述2. 数据类型.运算符与表达式3. C语言程序结构 4. VC6.0使用练习 知识详解01:C语言的历史 1. C语言与其它语言比较 汇编语言: (1).可直接对硬件进行操 ...
- 2008技术内幕:T-SQL语言基础
2008技术内幕:T-SQL语言基础 单表查询摘记 这里的摘抄来自<Microsoft SQL Server 2008技术内幕:T-SQL语言基础>,书中用到的案例数据库是这个 TSQLF ...
- C语言基础复习总结
C语言基础复习总结 大一学的C++,不过后来一直没用,大多还给老师了,最近看传智李明杰老师的ios课程的C语言入门部分,用了一周,每晚上看大概两小时左右,效果真是顶一学期的课,也许是因为有开发经验吧, ...
随机推荐
- socket--多进程,多线程服务器
一:概念: 我们知道IP地址是标志网络中不用主机的IP地址,而端口号就是同一台主机上标志不同进程的地址,IP地址和端口号标志网络中的唯一地址.(又称socket) 在TCP协议中,建⽴立连接的两个进程 ...
- Django中使用locals()函数的技巧
对 current_datetime 的一次赋值操作: def current_datetime(request): now = datetime.datetime.now() return rend ...
- 【BZOJ 3640】JC的小苹果 (高斯消元,概率DP)
JC的小苹果 Submit: 432 Solved: 159 Description 让我们继续JC和DZY的故事. “你是我的小丫小苹果,怎么爱你都不嫌多!” “点亮我生命的火,火火火火火!” 话 ...
- Eclipse 工具下Maven 项目的快速搭建
Eclipse 工具下Maven 项目的搭建 参考博文:https://www.cnblogs.com/iflytek/p/7096481.html 什么是Maven项目 简单来说,传统的Web项目: ...
- spring---transaction(5)---事务的体系
1.写在前面 事务的模型为3中: 本地事务模式. 编程事务模式. 声明事务模式. 例子1:本地事务模式 Connection conn=jdbcDao.getConnection(); Prepare ...
- 通过adb shell操作android真机的SQLite数据库
要通过命令行直接操作android真机上的SQLite数据库,可以直接通过adb shell来完成,不过,前提是必须获得root权限. 另外,android系统其实就是linux的shell,这个应该 ...
- 详解DHCP工作方法,并用wireshark对DHCP四个数据包抓包分析
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- Shell获取文件的文件名和扩展名的例子
这篇文章主要介绍了Shell获取文件的文件名和扩展名的例子,简明版的代码实例,看了就懂,需要的朋友可以参考下 basename example.tar.gz .tar.gz # => examp ...
- 在MyEclipse中修改类不重启tomcat
今天因为在调试一个程序,因为工程中用到spring,每次修改类代码时都要重启服务器,搞得很郁闷,于是上网找找有没有可以让java代码每次修改之后 直接加载到服务器的,找了一些还果真有,不过有些方法我试 ...
- AD域 根据 用户属性userAccountControl 来判断用户禁用属性
参考:https://support.microsoft.com/zh-cn/help/305144/how-to-use-the-useraccountcontrol-flags-to-manipu ...