理解 Go 中的函数

函数是过程编程的基石。它们有助于创建模块化代码,其中一项大工作可以分割成小段代码,并且可能是由不同的人编写的,它们在时间和空间上都是分开的。它们还有助于向用户隐藏实现细节。出于实际原因,函数是任何编程语言的关键部分。在这里,我们将介绍函数的整体概念及其在 Go 中的实现,以及编码示例。

初始化函数

函数 main() 和 init() 是保留给 Go 编译器使用的两个特殊用途函数。这两个函数都不接受任何参数,也不返回任何值。init() 函数是隐式声明的,我们不能从代码中的任何地方引用它,但我们可以在同一个程序中创建多个 init() 函数。在这种情况下,多个 init() 函数的执行顺序将按照它们被创建的顺序。如果在多个文件中创建了多个 init() 函数,那么它们的执行顺序将根据文件名的词法顺序。init() 函数的主要目的是在调用 main() 函数之前初始化全局变量。

主要功能

每一段 Go 代码都写在一个 main 包中,开始一个 Go 程序的包有一个名为 main() 的函数。这个函数是 Go 程序执行的入口点。这意味着这是第一个执行的函数(除了 init() 函数)。如前所述,main() 函数不接受任何参数,也不返回值。与 init() 不同,在 Go 程序中编写多个 main() 函数没有意义,因此是不允许的。

自定义函数

我们需要创建模块化代码的原因不止一个,这就是为什么从过程编程和面向对象编程的角度来看,函数都很重要。Go 为根据需要创建自定义函数提供了出色的支持。函数声明的语法结构非常简单。

函数声明

根据 Go 语法函数,声明以关键字 – func 开头。然后关键字后跟一个名为 function-name 的名称。命名函数的规则是它不能以数字或除下划线(’_’)以外的任何其他字符开头。良好的编程习惯是函数名称应与其贡献的值有意义地保持一致。这个想法是这个名字应该给程序员一个关于它的目的的提示。因此,像 _8TKK 这样的名称虽然在语法上是有效的,但并没有给出其用途的适当提示。诸如 _areaOfCircle 之类的名称可以很好地了解函数的实际作用。此外,_ADD 等函数名称与 _add 不同,Go 对命名中使用的字母大小写敏感。Go 函数的具体格式可以分为五个部分。


func function_name(list_of_parameters)(return_type) {
//...
//function_body
}
  1. func:Go 中专门用于创建函数的关键字
  2. function_name:在创建过程中给出的名称,通过该名称知道函数
  3. list_of_parameters:参数列表是指它采用的参数的数量和类型。参数在函数调用期间传递给函数。可以有零个或多个参数。如果没有参数,则括号留空。参数列表中的多个参数以逗号分隔。括号在任何情况下都是强制性的。有时最后一个参数前面有一个省略号 (…),表示该函数将接受零个或多个 []type 类型的参数。这种类型的函数称为可变参数函数。
  4. return_type:函数经过适当处理后可能返回给调用者的值。它是一个可选部分(包括括号),可以省略以表示该函数不返回任何内容。与 C 和 C++ 不同,Go 中的函数可能返回零个或多个值。具有一个或多个返回值的函数必须至少有一个 return 语句或调用 panic() 作为最后一个语句。
  5. function_body:函数体是编写函数逻辑的部分。它包含在花括号内。

下面的示例演示了不同类型的函数,例如零个或多个参数函数、零个或多个返回以及来自主函数的可变参数函数调用。


package main

import (
	"fmt"
	"math"
	"strings"
)

func main() {

	simpleFunction()

	showSquareRoot(56)

	fmt.Printf("three numbers 11,22,33 added %d\n", addThreeNumbers(11, 22, 33))

	fmt.Printf("Area Of Circle is %f\n", areaOfCircle(5.23))

	fmt.Println("Variadic function call")
	fmt.Println("Sum = ", addNNumbers(1, 2))
	fmt.Println("Sum = ", addNNumbers(1, 2, 3))
	fmt.Println("Sum = ", addNNumbers(1, 2, 3, 4, 5))
	fmt.Println("------------------------------------")

	a, b := 10, 20
	fmt.Printf("Before swap: The value of a,b is %d, %d\n", a, b)
	a, b = swap(a, b)
	fmt.Printf("After swap: The value of a,b is %d, %d\n", a, b)

}

func simpleFunction() {
	fmt.Println("simple function")
}

func showSquareRoot(num float64) {
	fmt.Printf("The square root of %v is %v\n", num, math.Sqrt(num))
}

func addThreeNumbers(a, b, c int) int {
	return (a + b + c)
}

func swap(a, b int) (int, int) {
	c := a
	a = b
	b = c
	return a, b
}

func doSomething(a, b, c float64, name string) (float64, float64, string) {
	mul := a * b * c
	add := a + b + c
	upper := strings.ToUpper(name)
	return mul, add, upper
}

func addNNumbers(numbers ...int) int {
	sum := 0
	for _, n := range numbers {
		sum += n
	}
	return sum
}

func areaOfCircle(radius float64) float64 {
	area := math.Pi * math.Pow(radius, 2)
	return area
}

输出:


simple function
The square root of 56 is 7.483314773547883
three numbers 11,22,33 added 66
Area Of Circle is 85.931670
Variadic function call
Sum =  3
Sum =  6
Sum =  15
------------------------------------
Before swap: The value of a,b is 10, 20
After swap: The value of a,b is 20, 10

闭包函数

在 Go 中,我们可以在函数中定义一个函数。这种类型的函数称为闭包函数。闭包函数是匿名的,除了没有名称外,其语法与普通函数几乎相同。这种类型的函数在我们不想创建单独的函数,也不希望一段代码成为函数现有逻辑的一部分的情况下特别有用。闭包函数有一些特殊用途。完整的解释需要单独的文章。为了补充基本概念,这里有一个关于如何编写闭包函数的简单示例。


func main() {

	str1, str2, str3 := addFileExtension("MyFile")

	fmt.Printf("File Names: %s, %s, %s", str1, str2, str3)

}

func addFileExtension(fileName string) (string, string, string) {

	toDocx := func(file string) string { return file + ".docx" }
	toTex := func(file string) string { return file + ".tex" }
	toPdf := func(file string) string { return file + ".pdf" }

	return toDocx(fileName), toTex(fileName), toPdf(fileName)
}

递归函数

调用自身的函数称为递归函数,相互调用的函数称为相互递归函数。递归函数的典型特征是它必须具有退出条件,因为它递归地调用自身。退出条件的目的是中断调用并确保函数最终在某个点停止。除此之外,递归函数就像普通函数一样。任何可以递归定义的逻辑也可以以非递归方式定义。但是递归函数的要点是,一些数据结构或算法,例如二叉树或数值计算,最好通过递归函数来表示。一个例子:


For example the recursive function for n-th number Fibonacci series can be written in Go as follows:

func fibonacci(num int) int {
	if num < 2 {
		return num
	}
	return fibonacci(num-1) + fibonacci(num-2)
}
 

最后的想法

Go 函数包含与其实现的逻辑一致的代码块或语句。例如,add() 函数可以将两个数字相加,convert() 函数可以将特定类型转换为另一种类型,等等。这个想法是使用函数将程序逻辑排列成可维护的部分。函数利用代码的可重用性,通常可以显着减少内存过载。函数通常取一些值作为参数,按照逻辑进行处理,然后返回一些值。可以有不带任何参数也不返回任何值的函数。