Go语言基础语法 - 04

72 阅读4分钟

函数

在 Golang 中,函数是代码的基本组成部分。函数可以接受参数并返回值。与许多其他编程语言不同,Golang 的变量类型是后置的,这意味着类型声明在变量名之后。

package main

import "fmt"

// add 函数实现两个整数相加
func add(a int, b int) int {
    return a + b
}

// add2 函数实现两个整数相加,参数类型简写
func add2(a, b int) int {
    return a + b
}

// exists 函数检查 map 中是否存在指定的键,并返回对应的值和一个布尔值
func exists(m map[string]string, k string) (v string, ok bool) {
    v, ok = m[k]
    return v, ok
}

func main() {
    // 调用 add 函数并打印结果
    res := add(1, 2)
    fmt.Println(res) // 输出: 3

    // 调用 exists 函数并打印结果
    v, ok := exists(map[string]string{"a": "A"}, "a")
    fmt.Println(v, ok) // 输出: A true
}

函数定义

在 Golang 中,函数定义的基本格式如下:

func functionName(parameterList) (returnTypeList) {
    // 函数体
}
  • func: 关键字,用于定义函数。
  • functionName: 函数名。
  • parameterList: 参数列表,参数类型在参数名之后。
  • returnTypeList: 返回类型列表,可以返回多个值。

参数类型后置

Golang 的参数类型声明在参数名之后。例如:

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

当多个参数类型相同时,可以简写:

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

多返回值

Golang 原生支持函数返回多个值,这在处理错误信息时非常有用。例如:

func exists(m map[string]string, k string) (v string, ok bool) {
    v, ok = m[k]
    return v, ok
}

命名返回值

函数可以为返回值命名,这样在函数体内可以直接使用这些变量,并且在函数结束时自动返回。例如:

func divide(a, b float64) (result float64, err error) {
    if b == 0 {
        err = fmt.Errorf("division by zero")
        return
    }
    result = a / b
    return
}

可变参数

Golang 支持可变参数,即函数可以接受不定数量的参数。例如:

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

匿名函数和闭包

Golang 支持匿名函数和闭包。例如:

func main() {
    add := func(a, b int) int {
        return a + b
    }
    fmt.Println(add(12)) // 3
    counter := func() func() int {
        count := 0
        return func() int {
            count++
            return count
        }
    }()
    fmt.Println(counter()) // 1
    fmt.Println(counter()) // 2
}

指针

在 Golang 中,指针是一种变量类型,用于存储另一个变量的内存地址。与 C 和 C++ 中的指针相比,Golang 对指针的操作更为有限,但仍然非常有用,特别是在需要修改传入参数的情况下。

package main

import "fmt"

// add2 函数试图将传入的整数参数加 2
func add2(n int) {
    n += 2
}

// add2ptr 函数将传入的整数指针参数指向的值加 2
func add2ptr(n *int) {
    *n += 2
}

func main() {
    n := 5
    add2(n)
    fmt.Println(n) // 输出: 5

    add2ptr(&n)
    fmt.Println(n) // 输出: 7
}
  1. 按值传递

    • 在 Golang 中,函数参数是按值传递的,这意味着传入的参数实际上是一个拷贝。对拷贝进行的任何修改不会影响原始变量。

    func add2(n int) {
        n += 2
    }
    
    • 功能: 该函数试图将传入的整数参数 n 加 2。
    • 无效修改: 因为 n 是一个拷贝,对 n 的修改不会影响到 main 函数中的变量 n

    在 main 函数中调用 add2 函数:

    func main() {
        n := 5
        add2(n)
        fmt.Println(n) // 输出: 5
    }
    
    • 结果: 输出仍然是 5,因为 add2 函数对 n 的修改是无效的。
  2. 使用指针传递

    通过传递指针,可以在函数中修改原始变量的值。使用 & 获取变量的地址,使用 * 解引用指针。

    func add2ptr(n *int) {
        *n += 2
    }
    
    • 功能: 该函数将传入的整数指针参数 n 指向的值加 2。
    • 有效修改: 使用 *n 解引用指针,直接修改指针指向的变量的值。这种修改是有效的,会影响到 main 函数中的变量 n

    在 main 函数中调用 add2ptr 函数:

    func main() {
        n := 5
        add2(n)
        fmt.Println(n) // 输出: 5
        add2ptr(&n)
        fmt.Println(n) // 输出: 7
    }
    
    • 结果: 输出变为 7,因为 add2ptr 函数对 n 的修改是有效的。
  3. 总结

    • 指针的用途: 指针主要用于在函数中修改传入的参数。
    • 按值传递: Golang 中的函数参数是按值传递的,传入的是参数的拷贝。
    • 指针传递: 通过传递指针,可以在函数中修改原始变量的值。
    • 指针操作: 使用 & 获取变量的地址,使用 * 解引用指针。