Go学习-Day3 | 青训营

50 阅读2分钟

[toc]

循环语句

  • 传统方法
  • func main() {
        for i := 1; i < 10; i++ {
            fmt.Println("hello!")
        }
    }
    
  • for - range方法
  • func main() {
        str := "abcde"
        for idx, val := range str {
            fmt.Printf("%v %c\n", idx, val)
        }
    }
    
  • idx是下标,val是值
  • go没有while和do-while使用for来实现
  •     for {
            if i > 10 {
                break
            }
            fmt.Println(i)
            i++
        }
    

函数

声明

  • func 函数名(形参列表)返回值列表 {}
  • func add(a int, b int) int {
        return a + b
    }
    
  • 分包写函数
  • package main
    ​
    import (
        "fmt"
        "go_code/project01/model"
    )
    ​
    func main() {
        fmt.Println(model.Add(1, 2))
    }
    ​
    
  • 包名和文件夹名可以不一致,这样下面调用的时候也要用另外的包名,一般来说,我们习惯于名字保持一致,这样我们导入包的时候,就就能知道包名是什么了。
  • 再复习一个点,Go语言没有public private关键字,是用变量和函数第一个字母大小写来判断公有还是私有,大写是公有,小写是私有。
  • 导包的路径,是从GOPATH/src 后面的部分,一直导到包文件夹。
  • 在同一包下,不能又相同的函数名,不支持函数的重载
  • 如果要编译可执行文件必须声明main包,main包是唯一的。

init函数

  • 每个源文件都可以包含一个init函数,这个函数会在main函数之前被调用,全局变量定义,init函数,main函数的顺序调用
  • 可能相当于类当中的构造函数

匿名函数

  • 相当于把整个函数体当作函数的名字,后面的括号就是传入的参数列表
  • func main() {
        res := func(a int, b int) int {
            return a + b
        }(1, 2)
        fmt.Println(res)
    }
    
  • 如果不带括号,可以重复调用匿名函数,类似lamda表达式
  •     res := func(a int, b int) int {
            return a + b
        }
        //fmt.Println(res)
        
        fmt.Println(res(1, 2))
    

闭包

  • func main() {
        f := func() func(int) int {
            var n int = 10
            return func(x int) int {
                n = x + n
                return n
            }
        }
        ff := f()
        ff(1)
        ff(2)
        fmt.Println(ff(3))
    }
    
  • 答案16
  • 这里是一个返回值是(int)int的匿名函数,返回了一个含有未知参数并且引用了n的匿名函数,对这个匿名函数多次调用。
  • 函数和引用的外部变量构成了闭包,相当于一个类,第一次调用得到一个匿名函数,可以类比成一个构造方法,构造出了一个类,n是类的一个成员。
  • 或者,我们这样想,这个匿名函数和他所引用的变量构成的闭包,在匿名函数第一次返回的时候,这些变量也在相同的作用域进行声明。

defer

  • to delay sth until a later time 推迟;延缓;展期(摘自牛津)
  • func main() {
        defer fmt.Println("ok1")
        defer fmt.Println("ok2")
        
        fmt.Println("ok3")
        fmt.Println("ok4")
        
    }
    
  • 输出顺序是:3->4->2->1
  • defer先不执行,等到函数快要释放的时候,defer执行顺序遵从栈的顺序,先进后出
  • 当语句压入栈的时候,相关引用的变量也会拷贝一份进入栈。