一、条件判断 if
1、条件判断
if true {
println(true)
}
2、初始化; 条件判断
比较有特色的是go
的if
支持初始化语句的执行。
- 可以减少行数
- 可以明确条件判断表达的意义
x := 1
if x++; x == 2 {
println("先计算,再判断")
}
if c := 3; x == 2 {
println("先赋值,再判断")
}
// 异常错误处理
if value, err := check(); err!=nil {
log.Println(err)
}
二、循环遍历 for
1、传统用法
初始化;判断;计算
for i := 0; i < 10; i++ {
println(i)
}
2、仅判断
相当于while i < 10 {},或者for ; x < 10 ; {}
i := 5
for i < 10 {
println(i)
i++
}
3、无限循环
相当于while true {}
i:=0
for {
println(i)
i++
if i > 20 {
break
}
}
三、条件判断 switch
1、传统用法
可以不用写break,默认就带break
switch x {
case 1:
println(1)
case 2:
println(2)
case 3:
println(3)
default:
println(0)
}
2、不传参,多条件判断
switch {
case x == 1:
println(1)
case x == 2:
println(2)
case x == 3:
println(3)
default:
println(0)
}
3、带初始化语句
会先执行初始化语句,再传参,
switch x++; x{
case 1:
println(1)
case 2:
println(2)
case 3:
println(3)
default:
println(0)
}
4、条件通过后,继续执行
因为每条case默认带break,所以条件通过后,会结束执行。要加fallthrough
switch x{
case 1:
println(1)
fallthrough
case 2:
println(2)
case 3:
println(3)
default:
println(0)
}
四、数组 array
个人看法: array和java中的 [3]Integer 相对,固定,而 slice 和 java中的ArrayList相对,可动态添加
1、两数组比较
length 长度不一样的数组,不是同类型,不可比较
a,b可比较,a,c不可比较
var a = [2]int{1,2}
var b = [2]int{1,2}
var c = [3]int{1,2,3}
2、定义未知长度数组
会按实际初始值数量自动分配内存
var b = [...]int{1,2,3}
// 二维数组及以上,其中...符号只能用在第一维
var c = [...][2]int{
{1,2},
{3,4},
}
3、数组复制
无论是赋值、传参,数组都会完整的复制
var k = [3]int{1,2,3}
var g = k
g[0] = 2
fmt.Println(k, g) // [1 2 3] [2 2 3]
若希望改变原始数组,可以使用指针或切片
var a = [3]int{1,2,3}
b := &a
b[2] = 4
fmt.Println(a,*b) // [1 2 4] [1 2 4]
var c = [3]int{1,2,3}
d := c[:]
d[2] = 5
fmt.Println(c,d) // [1 2 5] [1 2 5]
4、数组参数
数组在函数中作为参数,会被完整复制,不会影响原始数组
若希望改变原始数组,可以使用指针或切片
var e = [3]int{1,2,3}
var say = func (arr [3]int){
arr[2] = 9
fmt.Println(arr)
}
fmt.Println(e)
say(e)
fmt.Println(e)
// [1 2 3]
// [1 2 9]
// [1 2 3]
五、切片 slice
1、切片概念
切片本身是个只读对象,其工作机制类似数组指针的一种包装
切片优点:长度不固定,可以动态添加
type slice struct{
array unsafe.Pointer
len int // 表示切片当前实际元素的长度
cap int // 表示切片所引用的数组的真实长度,可理解为容量
}
那cap的作用是什么?
cap确定了切片初始分配的内存,超过cap后,会动态分配内存。cap也会被动态改变。
2、切片切割
x[起点:终点:容量(cap-start)],
切片取值是左闭右开,就是起点值会被取到,终点值不会被取到,起始值起点是0
x := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println(x[:])
fmt.Println(x[2:5])
fmt.Println(x[2:5:7])
fmt.Println(x[4:])
fmt.Println(x[:4])
fmt.Println(x[:4:6])
fmt.Println(len(x[2:5:7])) // 3 实际引用长度3
fmt.Println(cap(x[2:5:7])) // 5 容量有5
3、切片赋值
切片是指针操作,所以赋值给其他变量后的操作依然会影响原始切片
x := []int{1, 2, 3}
c := x[:3]
c[2] = 7
fmt.Println(c, x) // [1,2,7], [1,2,7]
4、切片比较
不能比较,就算是类型相同也不能,只能和nil比较
5、切片初始化
var a = make([]int, 3)
a = []int{1,2,3}
6、添加元素、复制切片
a := []int{1,2,3}
fmt.Println(a)
a = append(a, 4)
fmt.Println(a) // [1,2,3,4]
var a = []int{1,2,3}
var b = make([]int,3)
copy(b,a)
fmt.Println(b) // [1,2,3]
7、大数组切片引用
当一个大数组,len有100000,若有个切片需要长时间引用其中 [0,10]
这时候可以将切片复制,避免直接引用,释放大数组内存
a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // 假设这有100000个元素
b := make([]int, 3)
copy(b, a[:4])
fmt.Println(b)
六、常量 const
1、普通用法
const a = 1
2、同时声明多个常量
const a, b, c = 1, 2, 3