2.循环~切片基础语法和概念

167 阅读2分钟

1.循环与判断

代码示例

package main

import "fmt"

func main() {
	age := 19
	if age > 10 {
		fmt.Println("这是孩子")
	} else if age > 35 {
		fmt.Println("这是中年人")
	} else {
		fmt.Println("好好学习")
	}

	for i := 0; i < 10; i++ {
		fmt.Println("你好靓仔")
	}
}

golang有着类C语法,循环判断的if-else和for循环用法与C语言语法差不多

键值循环(for range)

  • 例子
s := "靓仔"
	for j, v := range s {
		fmt.Printf("%d %c\n\n", j, v)
	}
运行结果:
0//因为中文字符一般占3个字节,所以第一位0是靓仔,第三位3是仔
3
  • 作用
    • 遍历数组,切片,字符串。map及通道。
  • 区别
    • 1.数组,切片,字符串返回索引和值
    • 2.map返回键和值
    • 3.通道只返回通道内的值

switch和goto

代码示例

package main

import (
	"fmt"
)

func main() {
	//当i=5时候就跳出循环
	for i := 0; i < 10; i++ {
		if i == 5 {
			break
		}
		fmt.Println(i)
	}

	//当i=5时候,跳过此次for循环
	for i := 0; i < 10; i++ {
		if i == 5 {
			continue
		}
		fmt.Println(i)
	}

	n := 2
	switch n {
	case 1:
		fmt.Println("你是帅哥")
	case 2:
		fmt.Println("你很帅哦")
	    fallthrough
	case 3:
		fmt.Println("你好迷人")
	}
	//switch的第二种形式
	switch w := 3; w {
	case 1:
		fmt.Println("你是美女")
	case 2:
		fmt.Println("你很美哦")
	case 3:
		fmt.Println("我爱你")
	}

	for i := 0; i < 4; i++ {
		for j := 'a'; j < 'z'; j++ {
			if j == 'c' {
				goto xx
			}
			fmt.Printf("%v-%c\n", i, j)
		}
	}
	xx: //label标签
	fmt.Println("over")
}

fallthrough关键字

  • 定义
    • fallthrough可以执行满足条件case的下一个case

label标签

  • 定义
    • 在Golang中能使用Label的有goto,break,continue.
  • 用法
    • Label在continue, break中是可选的, 但是在goto中是必须的
    • 作用范围: 定义Label的函数体内.
    • Label可以声明在函数体的任何位置,不管Label声明在调用点的前面还是后面.
  • 注意点
    • 不能重复定义Label(也就是说不能有多个label)
    • Label在嵌套函数(闭包)是不可用的. 不管是在闭包里调用闭包外的Label, 还是在闭包外调用闭包里的Label
      • golang中也是发生在函数之间的,就是在一个函数中存在引用外部变量的行为,我们就称这是个闭包函数。

数组

代码示例

package main

import "fmt"

func main() {
	var a1 [3]bool
	var a2 [4]bool
	
	fmt.Println("a1: a2:",a1,a2)
}

注意点

  • 数组的长度是数组类型的一部分
    • 比如 [3]int和[4]int都是长度固定的数组,==但它们两个的类型是不同的,因为长度不同。==
  • 数组的可比较性
    • 如果数组的长度不同,那么它们就属于不同类型,没有任何可比较性。
    • 如果数组长度相等,则可以比较是否相等,当数组元素完全相等时,两个数组则相等。
  • 让编译器来推断长度初始化数组
arr := [...]int{1, 2, 3}
  • 数组是值类型
    • 由于数组是值类型,所以在作为参数传递给一个函数时,传递的是值拷贝

切片

package main

import "fmt"

func main() {
	//切片的定义
	var s1 []int //定义一个存放int类型元素的切片
	var s2 []string
	fmt.Println(s1, s2)
	s1 = []int{1, 2, 3}
	s2 = []string{"帅哥", "美女", "大帅哥"}
	fmt.Println(s1, s2)
	fmt.Println(s1 == nil) //切片是引用类型,不支持直接比较,只能和nil比较
	//长度和容量,len()函数求长度,cap()函数求容量
	fmt.Printf("len:%d cap(s1):%d\n", len(s1), cap(s1))
	fmt.Printf("len:%d cap(s2):%d\n", len(s2), cap(s2))
	//由数组得到切片
	a1 := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
	s3 := a1[0:4] //基于一个数组切割,左包含右不包含(左闭右开)
	fmt.Println(s3)
	s4 := a1[1:6]
	fmt.Println(s4)
	s5 := a1[:4] //=>[0:4]
	s6 := a1[3:] //=>[3:len(a1)]
	s7 := a1[:]  //=>[0:len(a1)]
	fmt.Println(s5, s6, s7)
	//切片容量是指底层数组的容量
	fmt.Printf("len(s5):%d cap(s5):%d\n", len(s5), cap(s5)) //len(s5):4 cap(s5):8
	//底层数组从切片的第一个元素到最后的元素数量
	fmt.Printf("len(s6):%d cap(s6):%d\n", len(s6), cap(s6)) //len(s6):5 cap(s6):5
	//切片再切片
	s8 := s6[3:]
	fmt.Printf("len(s8):%d cap(s8):%d\n", len(s8), cap(s8)) //len(s8):2 cap(s8):2
	//切片是引用类型,都指向底层的一个数组
	fmt.Println("s6:", s6)
	a1[6] = 1300
	fmt.Println("s6", s6)
	fmt.Println("s8:", s8)
}

知识点

创建切片

  • 利用make函数创建切片
格式:slice := make([]类型, 长度,容量)
  • 通过字面量创建切片
    • 这种方法和创建数组类似,只是不需要指定[]运算符里的值。初始的长度和容量会基于初始化时提供的元素的个数确定
strSlice := []string{"帅哥", "美女", "我"}
  • 数组和切片创建的区别
    • 如果在[]运算符里指定了一个值,那么创建的就是数组而不是切片。只有在 [] 中不指定值的时候,创建的才是切片。
// 创建有 3 个元素的整型数组
myArray := [3]int{10, 20, 30}
// 创建长度和容量都是 3 的整型切片
mySlice := []int{10, 20, 30}
  • nil切片
    • 只要在声明时不做任何初始化,就会创建一个 nil 切片
var IntNum []int
  • 空切片
    • 空切片的底层数组中包含0个元素,也没有分配任何存储空间。一般用来表示空集合
// 使用 make 创建空的整型切片
myNum := make([]int, 0)
// 使用切片字面量创建空的整型切片
myNum := []int{}

内置函数

  • append()
    • append()函数为切片追加元素
  • len()
    • len()函数求切片长度
  • cap()
    • cap()函数求切片容量

注意点

  • 切片获取
  //由数组得到切片
	a1 := [...]int{1, 2, 3, 4, 5, 6, 7, 8}
	s3 := a1[0:4] //基于一个数组切割,左包含右不包含(左闭右开)
  • 语法糖"..."
    • 表示可变参数,用于表示可以接受任意个个数但类型相同的参数
  • 切片都是引用类型
    • 本质都指向底层数组