函数

基本概念

image.png

基本语法

image.png

return

image.png

函数使用细节

  1. go函数形参和返回值列表都可以是多个、且数据类型可以是值类型也可以是引用类型
  2. 函数名首字母大写表示公有、小写表示私有
  3. 基本数据类型和数组都是值传递 (值拷贝),在函数内修改不会影响到原来的值

image.png

  1. 如果希望函数内修改函数外的值,需要使用指针,传递地址

    1. func test1(x int){
    2. x++
    3. fmt.Printf("test1 : %d\n",x)
    4. }
    5. func test2(x *int){
    6. *x++
    7. fmt.Printf("test2 : %d\n",*x)
    8. }
    9. func main() {
    10. var x int = 10
    11. test1(x)
    12. fmt.Println(x)
    13. test2(&x)
    14. fmt.Println(x)
    15. }

    image.png

  2. go不支持函数重载

  3. 函数也是一种数据类型,可以赋值给一个变量,通过该变量就可以实现函数的调用 ```go func test1(x int){ x++ fmt.Printf(“test1 : %d\n”,x) } func main() { var func1 = test1 func1(100) }

//输出 test1 : 101

  1. 函数也可以作为一种形参,并且调用
  2. ```go
  3. func test1(x int){
  4. x++
  5. fmt.Printf("test1 : %d\n",x)
  6. }
  7. func test2(add func(int),x int){
  8. add(x)
  9. }
  10. func main() {
  11. test2(test1,100)
  12. }
  13. //输出 test1 : 101
  1. Go支持自定义数据类型

    1. type mySum func(int,int) int //mySum等价于一个函数类型func(int,int) int
  2. Go支持对函数返回值命名

    1. func cal(n int,n2 int)(sum int,sub int){
    2. sum = n1 + n2
    3. sub = n1 - n2
    4. return
    5. }
  3. 可以用下划线 _ 忽略一个或多个返回值

  4. go 支持可变参数,放于参数列表最末

args… 数据类型 (args是slice切片,通过args[index]可以访问到各个值)

  1. func sum(args... int){
  2. re := 0
  3. for i:=0;i< len(args);i++ {
  4. re += args[i]
  5. }
  6. fmt.Println(re)
  7. }
  8. func main() {
  9. sum(1,2,3,4,5,6,7)
  10. }
  11. // 输出 : 28
  1. 变量作用域
  • 函数内部定义的变量叫局部变量,作用域仅在函数内部
  • 函数外部定义的变量叫全局变量,作用域在整个包都有效,如果其首字母大写
    则作用域在整个程序都有效。
  • 如果一个变量在一个代码块,如for/if,那么这个变量的作用域在该代码块

init函数

image.png
image.png
image.png

通常可以在init函数中完成初始化工作

  1. 如果一个文件中包含全局变量定义、init函数、main函数,则执行流程为

全局变量定义=》init函数=》main函数
image.png
image.png

  1. 外部导入执行顺序

image.png

匿名函数

  1. 仅调用一次

image.png

  1. 通过变量多次调用

image.png

闭包

闭包就是一个函数与其相关的引用环境组合成一个整体

  1. func AddUpper() func(int) int{
  2. var n = 10
  3. return func (x int) int {
  4. n = n + x
  5. return n
  6. }
  7. }
  8. func main() {
  9. f := AddUpper()
  10. fmt.Println(f(1))
  11. fmt.Println(f(2))
  12. fmt.Println(f(3))
  13. }
  14. //输出
  15. 11
  16. 13
  17. 16

理解:
var n = 10
return func (x int) int {
n = n + x
return n
}
就算是一个闭包。可以理解为: 闭包是类、函数是操作、n是字段。

案例

只需要传递一次后缀返回闭包,不用每次都传递后缀。

  1. func makeSuffix(suffix string) func(string) string{
  2. return func(name string) string {
  3. if strings.HasSuffix(name,suffix){
  4. return name
  5. }
  6. return name + suffix
  7. }
  8. }
  9. func main() {
  10. var myfun = makeSuffix("后缀")
  11. fmt.Printf(myfun("一个后缀")+"\n")
  12. fmt.Printf(myfun("一个前缀")+"\n")
  13. var myfun2 = makeSuffix("前缀")
  14. fmt.Printf(myfun2("一个后缀")+"\n")
  15. fmt.Printf(myfun2("一个前缀")+"\n")
  16. }

image.png

defer

image.png

  1. //当执行到defer语句时,吧defer后面的语句加到独立的栈中(defer栈)
  2. //当函数执行完毕、或者发生异常时,会从栈中按照先入后出的方式出栈执行
  3. func sum(n1 int,n2 int) int{
  4. defer fmt.Println(n1)
  5. defer fmt.Println(n2)
  6. res := n1 + n2
  7. fmt.Println(res)
  8. return res
  9. }
  10. func main() {
  11. sum(10,20)
  12. }
  13. //输出
  14. 30
  15. 20
  16. 10
  1. //当涉及到值的时候,当时的值也会被拷贝
  2. func sum(n1 int,n2 int) int{
  3. defer fmt.Println(n1)
  4. defer fmt.Println(n2)
  5. res := n1 + n2
  6. n1 = 0
  7. n2 = 0
  8. fmt.Println(res)
  9. return res
  10. }
  11. //输出
  12. 30
  13. 20
  14. 10

image.png

  1. 通常包名和其所在文件夹名一致
  2. 要使用其他包中的函数和路径时,要先引入对应的包 import
  3. package在文件第一行,然后是import指令
  4. 在import包时,路径从 $GOPATH 的 src下开始,不用带src,编译器自动从src下开始

    1. package main
    2. import "go_code/package2"
    3. //引入外部函数
    4. func main() {
    5. package2.Add(50,60)
    6. }
  5. 大写函数公有小写函数私有跨包访问只能访问公有

  6. 别名可以给包起个别名,起别名后只能用别名访问

    1. package main
    2. import nickname "go_code/package2"
    3. //别名
    4. func main() {
    5. nickname.Add(50,60)
    6. }
  7. 同一下不可以有相同函数名

  8. 如果要编译成一个可执行文件,就需要将包名声明为main

GOPATH 目录进行 build 操作生成可执行文件 go build main包路径(从src下开始写路径)
配置路径 go build -o bin\my.exe(在GOPATH下的bin文件夹下生成my.exe) main包路径image.png