Golang 函数创建

本文介绍了Go语言中的函数基础知识,包括如何创建自定义函数、返回多个值以及如何通过指针更改函数参数值。通过示例代码详细解释了main函数的使用,以及在函数中如何处理命令行参数。强调了Go函数的按值传递特性,并展示了如何通过指针实现函数内部对参数的修改。此外,还讨论了函数返回多个值的功能,以及如何通过弃用变量来忽略不必要的返回值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

在 Go 中,函数允许你将一组可以从应用程序的其他部分调用的语句组合在一起。 你可以使用函数来组织代码并使其更易于阅读,而不是创建包含许多语句的程序。 更具可读性的代码也更易于维护。

到目前为止,我们一直在调用 fmt.println() 函数,并且在 main() 函数中编写代码。 在本节中,我们将探讨如何创建自定义函数。 我们还将介绍一些可用于 Go 函数的其他技巧。


一、main 函数

与之交互的函数是 main() 函数。 Go 中的所有可执行程序都具有此函数,因为它是程序的起点。 你的程序中只能有一个 main() 函数。 如果创建的是 Go 包,则无需编写 main() 函数。 我们将在后续模块中介绍如何创建包。

在深入了解如何创建自定义函数的基本知识之前,让我们看看 main() 函数的一个重要特性。 你可能留意到,main() 函数没有任何参数,并且不返回任何内容。 但这并不意味着其不能从用户读取值,如命令行参数。 如要访问 Go 中的命令行参数,可以使用用于保存传递到程序的所有参数的 os 包 和 os.Args 变量来执行操作。

下面的代码从命令行读取两个数字,并为其求和:

package main

import (
    "os"
    "strconv"
)

func main() {
    number1, _ := strconv.Atoi(os.Args[1])
    number2, _ := strconv.Atoi(os.Args[2])
    fmt.println("Sum:", number1+number2)
}

os.Args 变量包含传递给程序的每个命令行参数。 由于这些值的类型为 string,因此需要将它们转换为 int 以进行求和。

若要运行程序,请使用以下命令:

go run main.go 3 5

输出:

sum: 8

二、自定义函数

下面是用于创建函数的语法:

func name(parameters) (results) {
    body-content
}

请注意,使用 func 关键字来定义函数,然后为其指定名称。 在命名后,指定函数的参数列表。 你可以指定零个或多个参数。 你还可以定义函数的返回类型,该函数也可以是零个或多个。 (我们将在下一节中讨论如何返回多个值)。在定义所有这些值之后,你可以编写函数的正文内容。

若要练习此技巧,我们将重构上一节的代码,为自定义函数中的数字求和。 我们将使用以下代码:

package main

import (
    "os"
    "strconv"
)

func main() {
    sum := sum(os.Args[1], os.Args[2])
    fmt.println("Sum:", sum)
}

func sum(number1 string, number2 string) int {
    int1, _ := strconv.Atoi(number1)
    int2, _ := strconv.Atoi(number2)
    return int1 + int2
}

此代码创建一个名为 sum 的函数,该函数采用两个 string 参数,并将它们强制转换为 int,然后返回求和所得的结果。 定义返回类型时,函数需要返回该类型的值。

在 Go 中,你还可以为函数的返回值设置名称,将其当作一个变量。 例如,你可以重构如下 sum 函数

func sum(number1 string, number2 string) (result int) {
	int1, _ := strconv.Atoi(number1)
	int2, _ := strconv.Atoi(number2)
	result = int1 + int2
	return
}

请注意,你现在需要将函数的结果值括在括号中。 你还可以在函数中使用该变量,并且只需在末尾添加 return 行。 Go 将返回这些返回变量的当前值。 在函数末尾编写 return 关键字非常简单方便,尤其是在有多个返回值时。 但我们 不 建 议 不建议 采用这种方法,因为它不太清楚函数返回的内容。

三、返回多个值

在 Go 中,函数可以返回多个值。 你可以采用类似于定义函数参数的方式来定义这些值。 换句话说,你可以指定一个类型和名称,但该名称是可选的。

例如,假设你想要创建一个函数,以将两个数字求和,又让它们相乘。 函数代码将如下所示:

func calc(number1 string, number2 string) (sum int, mul int) {
    int1, _ := strconv.Atoi(number1)
    int2, _ := strconv.Atoi(number2)
    sum = int1 + int2
    mul = int1 * int2
    return
}

你现在需要两个变量来存储函数的结果。 (否则就不会进行编译。)它的外观如下所示:

func main() {
    sum, mul := calc(os.Args[1], os.Args[2])
    fmt.println("Sum:", sum)
    fmt.println("Mul:", mul)
}

Go 的另一个有趣功能是,如果不需要函数的某个返回值,可以通过将返回值分配给 _ 变量来放弃该函数。 _ 变量是 Go 忽略返回值的惯用方式。 它允许程序进行编译。 因此,如果只需要求和,则可以使用以下代码:

func main() {
    sum, _ := calc(os.Args[1], os.Args[2])
    fmt.println("Sum:", sum)
}

四、更改函数参数值(指针)

将值传递给函数时,该函数中的每个更改都不会影响调用方。 Go 是“按值传递”编程语言。 这意味着每次向函数传递值时,Go 都会使用该值并创建本地副本(内存中的新变量)。 在函数中对该变量所做的更改都不会影响你向函数发送的更改。

例如,假设你创建了一个用于更新人员姓名的函数。 请注意,运行此代码时会发生的变化:

package main

func main() {
    firstName := "John"
    updateName(firstName)
    fmt.println(firstName)
}

func updateName(name string) {
    name = "David"
}

即使你在函数中将该名称更改为 David,输出仍为 John。 由于 updateName 函数中的更改仅会修改本地副本,因此输出不会发生变化。 Go 传递变量的值,而不是变量本身。

如果你希望在 updateName 函数中进行的更改会影响 main 函数中的 firstName 变量,则需要使用指针。 指针 是包含另一个变量的内存地址的变量。 当你发送指向某个函数的指针时,不会传递值,而是传递地址内存。 因此,对该变量所做的每个更改都会影响调用方。
在 Go 中,有两个运算符可用于处理指针:

  1. & 运算符使用其后对象的地址。
  2. ∗ * 运算符取消引用指针。 也就是说,你可以前往指针中包含的地址访问其中的对象。
    让我们修改前面的示例,以阐明指针的工作方式:
package main

func main() {
    firstName := "John"
    updateName(&firstName)
    fmt.println(firstName)
}

func updateName(name *string) {
    *name = "David"
}

运行前面的代码。 请注意,输出现在显示的是 David,而不是 John。

首先要做的就是修改函数的签名,以指明你要接收指针。 为此,请将参数类型从 string 更改为 string。 (后者仍是字符串,但现在它是指向字符串 的 指针。)然后,将新值分配给该变量时,需要在该变量的左侧添加星号 () 以暂停该变量的值。 调用 updateName 函数时,系统不会发送值,而是发送变量的内存地址。 这就是前面的代码在变量左侧带有 & 符号的原因。

代码如下(示例):


总结

  1. 需要注意函数体结构,返回值方式以及定义
  2. 函数是按值传递,如果需要更改函数参数值,需要使用指针来传值
  3. 可以返回多个值,而且还可以用"_"来忽略不需要的值
### Golang函数签名的相关知识 #### 什么是函数签名? 在 Go 语言中,函数签名为函数的定义提供了标准化的形式。它描述了一个函数的核心特征,包括名称、输入参数列表以及返回值类型[^3]。 #### 函数签名的基本结构 一个典型的函数签名由以下几个部分组成: 1. **函数名**:用于标识函数。 2. **参数列表**:指定函数接收的输入数据及其对应的类型。 3. **返回值类型**:声明函数执行完成后会返回的数据类型。 以下是函数签名的一般形式: ```go func functionName(parameter1 type1, parameter2 type2) (returnType1, returnType2) ``` #### 示例分析 以下是一个简单的函数签名示例,展示如何定义一个具有具体参数和返回类型的函数: ```go package main import "fmt" // 定义一个实现两数相加功能的函数 func addNum(x int, y int) int { ret := x + y return ret } func main() { result := addNum(5, 7) fmt.Println("Result:", result) } ``` 在这个例子中,`addNum` 的函数签名为 `func(x int, y int) int`,表示该函数接受两个整型参数并返回一个整型结果[^2]。 #### 多返回值的函数签名 Go 支持多返回值的功能,这使得函数设计更加灵活。例如,以下代码片段展示了带有多个返回值的函数签名: ```go package main import "fmt" // 返回商和余数 func divide(dividend float64, divisor float64) (float64, float64) { quotient := dividend / divisor remainder := dividend % divisor return quotient, remainder } func main() { q, r := divide(10, 3) fmt.Printf("Quotient: %.2f, Remainder: %.2f\n", q, r) } ``` 在此处,`divide` 的函数签名为 `func(float64, float64) (float64, float64)`,表明其接收两个浮点数作为参数,并返回两个浮点数值[^5]。 #### 匿名函数函数变量 除了常规命名函数外,Go 还支持匿名函数的概念。这些无名函数可以直接赋值给变量或者立即执行。下面是一段关于匿名函数的示例代码: ```go package main import "fmt" func main() { // 将匿名函数赋值给变量 f 并调用 var f func(int, int) int f = func(a, b int) int { return a * b } fmt.Println(f(3, 4)) // 输出 12 // 立即执行匿名函数 sum := func(numbers ...int) int { total := 0 for _, num := range numbers { total += num } return total }(1, 2, 3, 4, 5) fmt.Println(sum) // 输出 15 } ``` 上述代码说明了如何创建和使用匿名函数来简化逻辑处理过程[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值