GO语言学习(8)函数

目录

前言

1.函数基本声明与调用🌻

2. 多个返回值的函数🌻

3.函数参数传递方式🌻

3.1 值传递🌷

3.2 引用传递 🌷

4.可变参数函数 🌻

5.GO语言函数作为实参🌻

6.匿名函数与闭包🌻

7.高阶函数🌻

8.递归函数 🌻

 9.延迟调用defer 🌻

10.GO语言常用的内置函数 🌻


前言

        在Go语言中,函数是基本的代码组织和复用单元。函数可以接受输入参数,执行特定任务,并返回结果。Go语言中的函数设计简洁且功能强大,支持多返回值、匿名函数、闭包等特性。本文将详细介绍GO语言当中的函数🧐

1.函数基本声明与调用🌻

        Go语言中定义函数的基本语法如下:

func 函数名(参数列表) 返回值类型 {
    // 函数体
}
  • func:关键字,用于声明函数。

  • 函数名:函数的名称,遵循标识符命名规则。

  • 参数列表:函数的输入参数,格式为参数名 类型,多个参数用逗号分隔。

  • 返回值类型:函数的返回类型。如果函数没有返回值,可以省略;如果有多个返回值,需要用括号括起来。

  • 函数体:函数的具体实现逻辑。

💥示例代码

func add(a int, b int) int {  // 接受两个int类型的参数a和b,并返回它们的和
    return a + b
}
result := add(3, 5)            // 通过函数名和参数列表来调用函数
fmt.Println(result) // 输出: 8

2. 多个返回值的函数🌻

        Go语言支持函数返回多个值,这是Go语言的一个特色功能。多返回值的函数定义如下:

func 函数名(参数列表) (返回值类型1, 返回值类型2, ...) {
    // 函数体
    return 值1, 值2, ...
}

💥示例代码:

func swap(x, y string) (string, string) {
    return y, x
}

a, b := swap("hello", "world")
fmt.Println(a, b) // 输出: world hello

        如果某个返回值不需要使用,可以用下划线_忽略:

_, b := swap("hello", "world")

        并且Go语言允许为返回值命名,这样在函数体中可以直接使用这些变量,且return语句可以省略返回值。

💥示例代码:

func divide(a, b float64) (quotient float64, err error) { // 定义返回值名称
    if b == 0 {
        err = errors.New("除数不能为0")
        return
    }
    quotient = a / b
    return                      // 省略返回值
}

result, err := divide(10, 2)
if err != nil {
    fmt.Println(err)
} else {
    fmt.Println(result) // 输出: 5
}

3.函数参数传递方式🌻

        函数如果使用参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。调用函数,可以通过两种方式来传递参数:

传递类型描述
值传递值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
引用传递引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数

        默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。

3.1 值传递🌷

  • 基本原理:当使用值传递时,函数接收的是实际参数的一个副本。函数内部对这个副本的修改不会影响到原始的实际参数。这类似于在函数内部创建了一个局部变量,该变量的初始值是实际参数的值。

package main
import "fmt"

func modifyValue(x int) {
    x = 100 // 修改函数内部的副本
    fmt.Printf("Inside function: x = %d\n", x)
}

func main() {
    num := 10
    fmt.Printf("Before function call: num = %d\n", num)
    modifyValue(num)
    fmt.Printf("After function call: num = %d\n", num)
}

 上述代码最终输出结果如下:

Before function call: num = 10
Inside function: x = 100
After function call: num = 10

解释🪷:

  • main 函数中,num 的值为 10

  • 调用 modifyValue(num) 时,num 的值被复制到函数的参数 x 中。

  • modifyValue 函数中,x 的值被修改为 100,但这只是函数内部的副本,不会影响到 main 函数中的 num

  • 因此,main 函数中的 num 仍然保持为 10

3.2 引用传递 🌷

  • 基本原理:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。引用传递指针参数传递到函数内。

package main
import "fmt"

func modifyValue(x *int) { // 接收一个指针
    *x = 100 // 通过指针修改原始变量
    fmt.Printf("Inside function: x = %d\n", *x)
}

func main() {
    num := 10
    fmt.Printf("Before function call: num = %d\n", num)
    modifyValue(&num) // 传递变量的地址
    fmt.Printf("After function call: num = %d\n", num)
}

 上述代码最终输出结果如下:

Before function call: num = 10
Inside function: x = 100
After function call: num = 100

解释🪷

  • main 函数中,num 的值为 10

  • 调用 modifyValue(&num) 时,传递的是 num 的地址。

  • modifyValue 函数中,通过 *x(解引用)直接修改了 num 的值。

  • 因此,main 函数中的 num 的值被修改为 100

4.可变参数函数 🌻

        Go语言支持可变参数函数,即函数的参数数量不固定。可变参数通过...类型来定义,函数内部会将可变参数视为切片。

func sum(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

fmt.Println(sum(1, 2, 3))       // 输出: 6
fmt.Println(sum(1, 2, 3, 4, 5)) // 输出: 15

5.GO语言函数作为实参🌻

        Go 语言可以很灵活的创建函数,并作为另外一个函数的实参。

💥示例代码:

package main
import (
   "fmt"
   "math"
)

func main(){
   /* 声明函数变量 */
   getSquareRoot := func(x float64) float64 {
      return math.Sqrt(x)
   }

   /* 使用函数 */
   fmt.Println(getSquareRoot(9))   // 输出9
}

6.匿名函数与闭包🌻

        Go语言支持匿名函数,即没有函数名的函数。匿名函数可以直接定义并调用,也可以赋值给变量。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。而闭包是指一个函数捕获并保存了其外部作用域的变量。闭包在Go语言中非常有用,常用于实现函数工厂或延迟计算。

package main
import "fmt"

func main() {
    // 定义一个匿名函数并将其赋值给变量add
    add := func(a, b int) int {
        return a + b
    }

    // 调用匿名函数
    result := add(3, 5)
    fmt.Println("3 + 5 =", result)

    // 在函数内部使用匿名函数
    multiply := func(x, y int) int {
        return x * y
    }

    product := multiply(4, 6)
    fmt.Println("4 * 6 =", product)

    // 将匿名函数作为参数传递给其他函数
    calculate := func(operation func(int, int) int, x, y int) int {
        return operation(x, y)
    }

    sum := calculate(add, 2, 8)
    fmt.Println("2 + 8 =", sum)

    // 也可以直接在函数调用中定义匿名函数
    difference := calculate(func(a, b int) int {
        return a - b
    }, 10, 4)
    fmt.Println("10 - 4 =", difference)
}

上述代码最终输出结果为:

3 + 5 = 8
4 * 6 = 24
2 + 8 = 10
10 - 4 = 6

7.高阶函数🌻

        高阶函数是指可以接受函数作为参数或返回函数的函数。Go语言中函数是一等公民,可以作为值传递。

func apply(op func(int, int) int, a, b int) int {
    return op(a, b)
}

result := apply(func(a, b int) int {
    return a + b
}, 3, 5)
fmt.Println(result) // 输出: 8

解释🪷:

  • apply 是一个函数,它接收三个参数:

    • op:这是一个函数类型的参数,其类型为 func(int, int) int。这意味着 op 是一个函数,它接收两个整数参数并返回一个整数。

    • ab:这两个是普通的整数参数。

  • apply 函数内部,调用了 op(a, b),并将结果返回。

  • 这里的 op 是一个函数,apply 函数的作用是将 ab 作为参数传递给 op,并返回 op 的执行结果。

result := apply(func(a, b int) int {
    return a + b
}, 3, 5)
  • 在调用 apply 函数时,传递了一个匿名函数作为 op 参数。

       匿名函数的定义如下:

func(a, b int) int {
    return a + b
}
  • 这是一个函数字面量,它接收两个整数参数 ab,并返回它们的和。

8.递归函数 🌻

        Go语言支持递归函数,即函数调用自身。递归函数通常用于解决分治问题,如计算阶乘、斐波那契数列等。以下例子为一个计算阶乘的代码:

func factorial(n int) int {
    if n == 0 {
        return 1
    }
    return n * factorial(n-1)
}

fmt.Println(factorial(5)) // 输出: 120

 9.延迟调用defer 🌻

         Go语言中的defer语句用于延迟函数的执行,直到包含它的函数返回为止。defer通常用于资源释放、关闭文件等操作。

🌱基本语法

defer functionCall()
  • defer 关键字后面跟着一个函数调用。

  • defer 的函数调用会在其所在的函数返回之前执行,无论该函数是正常返回还是因为错误而返回。

🌱defer执行时机: 

  • defer 语句被执行时,函数调用不会立即执行,而是被推迟到其所在的函数返回之前。

  • 如果一个函数中有多个 defer 语句,它们会按照 后进先出(LIFO) 的顺序执行,即最后一个 defer 的函数调用会最先执行。

package main
import "fmt"

func main() {
    defer fmt.Println("First defer")
    defer fmt.Println("Second defer")
    defer fmt.Println("Third defer")

    fmt.Println("Function body")
}

 上述代码输出如下:

Function body
Third defer
Second defer
First defer

defer 语句按照它们出现的顺序被压入栈中。当函数返回时,defer 的函数调用按照后进先出的顺序执行。

💥示例——关闭文件

package main

import (
    "fmt"
    "os"
)

func main() {
    file, err := os.Open("example.txt")
    if err != nil {
        fmt.Println("Error opening file:", err)
        return
    }
    defer file.Close() // 确保文件在函数返回时关闭

    // 在这里读取文件内容
    fmt.Println("File opened successfully.")
}

解释🪷

  • os.Open 打开一个文件,返回一个文件对象和可能的错误。

  • 使用 defer file.Close() 确保文件在 main 函数返回时被关闭,无论是否发生错误。

  • 如果在读取文件内容时发生错误,file.Close() 仍然会被调用。

10.GO语言常用的内置函数 🌻

函数签名功能描述
append(slice []T, elems ...T) []T向切片追加元素,返回新的切片
cap(x) int返回切片、数组或通道的容量
close(c chan<- Type)关闭通道,使其不能再发送数据
complex(real, imag float64) complex128创建一个复数
copy(dst, src []Type) int将 src 的内容复制到 dst,返回复制的元素数量
delete(m map[Type]Type, key Type)从映射中删除指定的键
imag(c complex128) float64返回复数的虚部
len(x) int返回切片、数组、字符串或映射的长度
make([]T, len, cap)创建切片、映射或通道
new(Type)分配内存,返回指向分配内存的指针
panic(v interface{})触发运行时错误,终止当前函数的执行
recover()恢复从 panic 中恢复,仅在 defer 函数中有效
real(c complex128) float64返回复数的实部

        这些函数是 Go 语言的内置函数,可以直接在代码中使用,无需额外导入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值