10.函数

予早 2024-12-11 21:23:56
Categories: Tags:
func 函数名 (形参列表) (返回值参数列表) {
    ...
    return 返回值列表
}

基本结构

package main

import "fmt"

func add(a int, b int) int {
    return a + b
}

func main() {
    fmt.Println(add(1, 1))
}

入参

入参类型简化书写

package main

import (
    "fmt"
)

func add(num1, num2 int) int { // 改成func add(num1 int, num2) int会报错
    return num1 + num2
}

func main() {
    fmt.Printf("%T", add) // func(int, int) int
}

支持可变参数,被作为slice处理

package main

import (
    "fmt"
)

func argsDemo(args ...int) {
    fmt.Printf("%v, %T\n", args, args)
    for _, value := range args {
        fmt.Println(value)
    }
}

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

出参

返回值参数只有一个时,返回值参数列表的括号可以省略,多个返回值参数必须带括号

支持按位置的多返回值,接受也是按位置逐一接收

package main

import "fmt"

func div(num1 int, num2 int) (int, int) {
    //必须按照位置返回参数
    return num1 / num2, num1 % num2
}

func main() {
    merchant, remainder := div(6, 3)
    fmt.Println(merchant, remainder)
}

支持具名返回值,接收是按位置接收

package main

func div1(num1 int, num2 int) (int, int) {
    //必须按照位置返回参数
    return num1 / num2, num1 % num2
}

func div2(num1 int, num2 int) (merchant int, remainder int) {
    //return 1, 1 // 可以按照位置返回参数
    merchant = num1 / num2
    remainder = num1 % num2
    return // 可以根据名称自动返回
}

函数作为参数

package main

import (
    "fmt"
    "math"
)

// run1
// 接收两个参数,第一个参数是一个float64,第二个参数是一个函数,该函数接收一个float64的参数并返回一个float64的参数
func run1(num float64, function func(float64) float64) float64 {
    fmt.Printf("num=%f, func=%T\n", num, function)
    return function(num)
}

// f 定义一个类型 f,该类型为一个函数类型,其中该函数入参为一个float64,以及返回值是一个float64
type f func(float64) float64 //函数可以通用

func run2(num float64, function f) float64 {
    fmt.Printf("num=%f, func=%T\n", num, function)
    return function(num)
}

func main() {
    fmt.Println(run1(-3.14, math.Abs))
    // num=-3.140000, func=func(float64) float64
    // 3.14
    fmt.Println(run2(-3.14, math.Abs))
    // num=-3.140000, func=main.f
    // 3.14
}

匿名函数

  1. 定义匿名函数时直接调用
  2. 将匿名函数赋给变量,通过变量调用,局部变量和全局变量会导致函数可调用范围不一样
package main

import "fmt"

func main() {
    result := func(num1 int, num2 int) int { return num1 + num2 }(1, 1)
    fmt.Println(result)

    f := func(num1 int, num2 int) int { return num1 - num2 }

    fmt.Println(f(1, 1))
}

函数闭包

闭包函数相当于内部维护了一部分共享的数据,每次调用都会使用同一部分数据而非副本,当然也可以不维护

package main

import "fmt"

func adder() func(int) int {
    sum := 0
    return func(i int) int {
        sum = i + sum
        return sum
    }
}

func main() {
    f := adder()
    sum := f(1)
    fmt.Println(sum) // 1
    sum = f(1)
    fmt.Println(sum) // 2
}

内置函数

len、cap

package main

import (
    "fmt"
)

func main() {
    // len 内置函数返回 v 的长度
    // 根据 v 的类型取值有:
    // 数组:数组v中元素的数量
    // 数组指针:数组*v中的元素
    // 切片、映射:v 中元素的数量,若 v 为 nil,则返回 0
    // 通道:
    // 详见Go语言规范 长度和容量 一节

    fmt.Println(len("abc"))

    // cap 内置返回 v 的容量
    // 根据 v 的类型取值有:
    // 数组:v 中元素的数量,同 len
    // 数组指针:*v 中元素的数量
    // 切片:二次切片可用的最大长度,若 v 为 nil,cap(v) 为 0
    // 通道:通道缓存容量,若 v 为 nil,cap(v) 为 0
    fmt.Println(cap([]int{1, 2, 3}))
}

new、make

package main

import (
    "fmt"
)

func main() {

    // func new(Type) *Type
    // new 内置函数用于申请内存
    // 入参:第一个参数是一个 Type 类型参数
    // 出参:返回一个 *Type 指针,指针指向一个新的 Type 类型数据的零值
    num := new(int)
    fmt.Println(num, *num) // 0xc00000a0b8 0

    // func make(t Type, size ...IntegerType) Type
    // 内置函数 make 用于针对某类型的对象申请内存和初始化,类型有 slice、map、chan(only)
    // slice:size 指定长度,slice的容量等于其长度,第二个整数参数可以指定一个不等于长度的容量,容量不能小于长度
    // 例如
    // map:
    // channel:以 size 为指定容量创建和初始化 channel buffer,若 size 为 0,或者 size 被省略,channel 为无 buffer
    a := make([]int, 0, 10)
    fmt.Printf("%T, %v", a, a) // []int, []
}

recover、painc

见yi’chang