Go基础学习四之函数function、结构struct、方法method

Corwien · · 764 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Go编程语言:支持并发、垃圾回收的编译型系统级编程语言!本文主要是按照无闻的《Go 编程基础》开源视频学习并记录笔记。

一、函数function

1、基本概念

函数是基本的代码块,用于执行一个任务。
Go 语言最少有个 main() 函数
函数声明告诉了编译器函数的名称,返回类型,和参数
Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的函数个数。

2、函数定义

函数定义格式如下:

func function_name( [parameter list] ) [return_types] {
   函数体
}

函数定义解析:

  • func:函数由 func 开始声明
  • function_name:函数名称,函数名和参数列表一起构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。

示例:

/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
   /* 声明局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

3、函数特性

  • Go 函数不支持嵌套、重载和默认参数
  • Go 函数支持无需声明原型、不定长度变参、多返回值、命名返回值参数、匿名函数、闭包
  • 定义函数使用关键字func,且左大括号不能另起一行
  • 函数也可以作为一种类型使用
ackage main


import "fmt"  

func main() {
  A(1, 2, 3, 4 ,5)
}


// ... 不定长变参
func A(a ...int) {
    fmt.Println(a)
    
}

输出:

➜  myfirstgo go run func.go
[1 2 3 4 5]

不定长变参特性:
1、不可以在不定长变参后边添加其他参数 func b(a ...int, b string), 这种写法是错误
2、不定长参数可以放在其他参数后边 func b(b string, a ...int)

4、匿名函数

func main() {

  // 将一个函数赋值一个变量,该变量是函数类型
  a := func(){
    fmt.Println("匿名函数")
}

  // 调用
  a()
}

5、闭包

/**
* 闭包函数
*
* 该闭包函数接收一个int型参数,其返回值是函数类型
*
*/
func closure(x int) func(int) int {
    fmt.Println("%p\n", &x)
    return func (y int) int {

        fmt.Println("%p\n", &x)
        fmt.Println(x)
        fmt.Println(y)
    
        return x + y
    }
}

func main() {
  f := closure(10);
  fmt.Println(f(1))
  fmt.Println(f(2))
}

打印结果:

➜  myfirstgo go run func.go
%p
 0xc42000e228
%p
 0xc42000e228
10
1
11
%p
 0xc42000e228
10
2
12
➜  myfirstgo

6、defer

  • defer 的执行方式类似其他语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行
  • 即使函数发生严重错误也会执行
  • 支持匿名函数的调用
  • 常用于资源清理、文件关闭、解锁以及记录时间等操作
  • 通过与匿名函数配合可在return之后修改函数计算结果
  • 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址
  • Go没有异常机制,但有 panic/recover 模式来处理错误
  • Panic 可以在任何地方引发,但 recover 只有defer 调用的函数中有效

简单的测试:


func main() {
  fmt.Println("a")
  
  defer fmt.Println("b")
  defer fmt.Println("c")
}

上边的执行会打印什么结果呢? 会打印:a b c 吗?
让我们实际执行一下:

  myfirstgo go run func.go
a
c
b

实际打印的结果为:a c b

defer 的执行方式类似其他语言中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行

使用闭包

func main() {
  for i := 0; i < 3; i++ {

       // defer 普通调用
       // defer fmt.Println(i)  // 打印 2 1 0

     // 使用闭包,引用局部变量
       defer func () {
           fmt.Println(i)
       }()

  }
  
}

打印结果:

➜  myfirstgo go run func.go
3
3
3

panic 使用示例

func main() {
  A()
  B()
  C()
}

func A() {
    fmt.Println("FUNC A")
}

func B() {

   // 匿名函数,如果没有参数,则末尾需要使用括号
    defer func() {
        if err := recover(); err != nil {
            fmt.Println("Recover is B")

        }
        
    }()

    panic("B panic")

}

func C() {
    fmt.Println("FUNC C")
}

打印结果:

➜  myfirstgo go run func.go
FUNC A
Recover is B
FUNC C
➜  myfirstgo

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:Corwien

查看原文:Go基础学习四之函数function、结构struct、方法method

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

764 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传