label

Go语言中支持label语法:分别是break labelgoto labelcontinue label

==break与其他语言类似,但是不和switch搭配使用,goto与continue没有很大区别==

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
label:
for i := 1; i <= 10; i++ {
for j := 1; j <= 5; j++ {
if i == 8 && j == 4 {
break label
}
fmt.Print("+")
}
fmt.Print("\n")
}
}

函数

标准函数

  1. void 不返回

    1
    2
    3
    func getSum(n1 int, n2 int) {
    fmt.Println(n1 + n2)
    }
  2. 返回特定类型

    1
    2
    3
    func getSum(n1 int, n2 int) int {
    return n1 + n2
    }
  3. 多个返回值

    • 普通
    1
    2
    3
    4
    5
    func getSum(n1, n2 int) (int, int) {
    sum := n1 + n2
    mult := n1 * n2
    return sum, mult
    }
    • 返回值命名
    1
    2
    3
    4
    5
    func getSum(n1, n2 int) (sum, mult int) {
    sum = n1 + n2
    mult = n1 * n2
    return
    }

匿名函数 ==额外:指针修改值的问题==

  1. 函数数据类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    func getSum(n1, n2 int) (sum, mult int) {
    sum = n1 + n2
    mult = n1 * n2
    return
    }

    func main() {
    fmt.Printf("type is %T", getRes)
    // type is func(int, int) (int, int)
    }
  1. 匿名函数

    • 声明变量的形式声明函数 ==这里与JS箭头函数()=>{}类似==

      1
      2
      3
      4
      5
      6
      7
      var getRes = func(n1, n2 int) (sum, mult int) {
      sum = n1 + n2
      mult = n1 * n2
      return
      }
      a, b := getRes(1, 2)
      fmt.Println(a, b)
    • 匿名函数立即执行

      1
      2
      3
      4
      5
      6
      a, b := func(n1, n2 int) (sum, mult int) {
      sum = n1 + n2
      mult = n1 * n2
      return
      }(1, 2)
      fmt.Println(a, b)

defer函数

与JS异步函数的执行(EventLoop)不同,在JS中分为宏任务队列与微任务队列,遇到Promise.then、Object.observe…将会将其push到当前宏任务的微任务队列中,遇到setTimeout、setInterval…将会push到宏任务队列中。

  1. 当前宏任务结束后,将处理当前宏任务的微任务队列中的任务;
  2. 当前宏任务的微任务队列全部完成后,将处理宏任务队列中的下一个宏任务。

在Go中,defer函数是进行==压栈==处理,即按顺序的第一个defer函数将在最后进行。(类似于宏任务与微任务==栈==)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func deferFunc1() {
fmt.Println(1)
}

func deferFunc2() {
fmt.Println(2)
}

func main() {
defer deferFunc1()
defer deferFunc2()
fmt.Println(3)
}

// 3
// 2
// 1

init函数

  1. 说明
    • init函数先于main函数自动执行
    • 每个包中可以有多个init函数,每个包中的源文件中也可以有多个init函数
    • init函数没有输入参数、返回值,也未声明,所以无法引用
    • 不同包的init函数按照包导入的依赖关系决定执行顺序
    • 无论包被导入多少次,init函数只会被调用一次,也就是只执行一次
    • init函数在代码中不能被显示的调用,不能被引用(赋值给函数变量),否则会出现编译错误
    • Go程序仅仅想要用一个package的init执行,我们可以这样使用:import _ “test_xxxx”,导入包的时候加上下划线就ok了
    • init函数不应该依赖任何在main函数里创建的变量,因为init函数的执行是在main函数之前的
  1. init执行顺序:

    • 单个源文件: init 函数执行顺序与其定义顺序一致,从上到下。
    • 单个package:根据文件名的 字典序 来确定。
    • main引入多个package
      • 不存在依赖:对于不同的包,如果不相互依赖的话,按照 main 包中导入顺序调用包的 init 函数,最后再调用 main 包的 init 函数。
      • 存在依赖:如果 package 存在依赖,不同包的 init 函数按照包导入的依赖关系决定执行顺序。 调用顺序为最后被依赖的最先被初始化,如导入顺序 main > a > b > c,则初始化顺序为 c > b > a > main,依次执行对应的 init 方法。