Go语言基础之函数

函数

1. 定义格式

  • 基本组成:关键字func、函数名、参数列表、返回值、函数体和返回语句
  • 只有一个返回值且不声明变量,可以省略括号

2. 自定义函数

1. 无参无返回值
func TestFunc() {
	a := 2
	fmt.Println("This is a test func, a is ", a)
}

func main() {
	TestFunc()    //无参无返回值函数调用
}
2. 有参无返回值

1). 普通参数列表

  • 定义函数时,在函数名后边 ( ) 定义的参数叫形参
  • 调用函数传递的参数叫实参
  • 参数传递,只能由实参传递给形参
    func TestFunc1(a, b int) {
    	fmt.Println("a = ", a)	
    	fmt.Println("b = ", b)	
    }
    
    func main() {
    	TestFunc1(0, 12)
    }
    

2). 不定参数列表

  • 不定参数类型

    • 指函数传入的参数个数为不定数量

    • 需要将函数定义为接受不定参数类型

    • 传递的实参可以是0或多个

      func TestFunc(args ...int){
      	fmt.Println(len(args))
      }
      
  • 不定参数的传递

    	func func1(tmp ...int) {
    		for _, data := range tmp{
    			fmt.Printin(data)
    		}
    	}
    	
    	func func2(tmp ...int) {
    		for _, data := range tmp{
    			fmt.Printin(data)
    		}
    	}
    	
    	func Test(args ... int) {
    		// 全部参数传递给Test
    		func1(args...)
    
    		// 只把后两个参数传递
    		// func2(args[2:]...)
    	}
    
    	func main() {
    		Test(1, 2, 3, 4)
    	}
    
3. 无参有返回值
  • 有返回值的函数,必须有明确的终止语句
  • 官方建议,最好命名返回值
  • 1). 一个返回值
    func Test() int{
    	return 123
    }
    
    // 给返回值命名
    func TestName() (v int) {
    	v = 1
    	return v // 也可直接return
    }
    
  • 2). 多个返回值
    func Test() (a b, int, c string){
    	a, b = 1, 2
    	c = 'str'
    	return
    }
    
4. 有参有返回值

3. 递归函数

4. 函数类型

  • 函数也是一种数据类型
  • 通过type来定义
func Add(a, b, int) int {
	return a + b
}

type FuncName func(int, int) int

func main() {
var fTest FuncName
fTest = Add
result = fTest(10, 20)  // 等价于Add(10, 20)
}
  • 回调函数
    • 函数有一个参数是函数类型,就是回调函数
      type FuncType func(int, int) int
      
      func Add(a, b, int) int {
      	return a + b
      }
      
      func Calc(a, b int, f FuncType) (result int) {
      	result = f(a, b)
      	return
      }
      
      func main() {
      	a := Calc(1, 1, Add)
      }
      

5. 匿名函数与闭包

  • 匿名函数:没有函数名字
    • 函数的返回值是一个匿名函数,返回一个函数类型
  • 闭包
    • 以引用方式捕获外部变量
    • 闭包不关心变量和常量是否超出作用域,只要闭包还在使用,这些变量还会存在
    • (变量的生命周期不是由它的作用域决定,变量仍隐式存在于函数中)

6. 延迟调用defer

1. defer的作用
  • 关键字defer用于延迟一个函数或方法
  • 只能出现在函数或方法的内部
2. 多个defer执行顺序
  • 后进先出的顺序执行
  • 哪怕函数或某个延迟调用发生错误,这些调用仍旧会被执行
3. defer与匿名函数结合使用
func main() {
    a, b := 10, 20
    defer func(x int) {
        fmt.Println("defer:", x, b) // b 闭包引用
    }(a)

    a += 10
    b += 100

    fmt.Printf("a = %d, b = %d\n", a, b)

    /*
        运行结果:
        a = 20, b = 120
        defer: 10 120
    */
}

7. 获取命令行参数

package main

import (
    "fmt"
    "os"
)

func main() {
    args := os.Args //获取用户输入的所有参数

    //如果用户没有输入,或参数个数不够,则调用该函数提示用户
    if args == nil || len(args) < 2 {
        fmt.Println("err: xxx ip port")
        return
    }
    ip := args[1]   //获取输入的第一个参数
    port := args[2] //获取输入的第二个参数
    fmt.Printf("ip = %s, port = %s\n", ip, port)
}

8. 作用域

  • 作用域为已声明标识符所表示的常量、类型、变量,函数或包在源代码中的作用范围
1. 局部变量
  • 定义在 { } 里面的变量就是局部变量,只能在 { } 里有效
  • 执行到定义变量那句时,才开始分配空间,离开作用域会自动释放
2. 全局变量
  • 在函数体外声明的变量称之为全局变量
  • 全局变量可以在整个包甚至外部包(被导出后)使用
3. 不同作用域同名变量
  • 在不同作用域可以声明同名的变量
  • 其访问原则为:
    • 在同一个作用域内,就近原则访问最近的变量
    • 如果此作用域没有此变量声明,则访问全局变量
    • 如果全局变量也没有,则报错。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值