Go语言入门基础(六)——函数

173 阅读4分钟

阅读本文前,建议已掌握基本C语言语法及规范,本文将更加侧重Go语言和C系列语言的区别以达到快速上手的目的

本文主要参考《Go语言圣经(中文版)》及个人实践撰写,具体可参考: Go语言圣经

本文作为该系列第六篇,也是基础篇的最后一篇,将重点介绍函数

函数声明

在本专栏的第二篇中介绍了Go语言的4种声明方式:var/const/type/func,其中func对应的就是函数的声明,标准语法如下:

func 函数名 (参数列表) (返回列表) {
    /* body */
}

具体使用及简化声明方法如下例:

package main

import "fmt"

func Standard_Statement(x int, y int, a float64, b float64) (re float64) {
	re = float64(x*y) + a
	return re
}

func Simple_Statement_1(x, y int, a, b float64) (re float64) {
	re = float64(x*y) + a
	return re
}

func Simple_Statement_2(x, y int, a, b float64) float64 {
	return float64(x*y) + a
}

func Simple_Statement_3(x, y int, a, _ float64) float64 { //or a float64, _ float64
	return float64(x*y) + a
}

func main() {
	fmt.Println(Standard_Statement(1, 2, 3.4, 5.6))
	fmt.Println(Simple_Statement_1(1, 2, 3.4, 5.6))
	fmt.Println(Simple_Statement_2(1, 2, 3.4, 5.6))
	fmt.Println(Simple_Statement_3(1, 2, 3.4, 5.6))
}

参考以上代码,四个函数实现的功能其实是相同的,第一个标准声明Standard_Statement是最标准且繁琐的声明形式;第二个声明Simple_Statement_1对参数列表进行简化,归类了相同类型的变量;Simple_Statement_2对返回参数进行简化,在该函数功能中返回值并不需要变量名(计算较为简单,可以直接在return语句中计算),因此该简化方式为无名返回值方式,可以去掉括号,只保留返回值数据类型;Simple_Statement_3对参数列表中未用到的参数进行简化,用下划线_(Go语言圣经原版中称为blank identifier)替代。

不出意料运行结果应该相同: image.png

可以使用占位符%T将以上演示结果显得更加直观:

//本段代码和上一段仅有main()函数不同
package main

import "fmt"

func Standard_Statement(x int, y int, a float64, b float64) (re float64) {
	re = float64(x*y) + a
	return re
}

func Simple_Statement_1(x, y int, a, b float64) (re float64) {
	re = float64(x*y) + a
	return re
}

func Simple_Statement_2(x, y int, a, b float64) float64 {
	return float64(x*y) + a
}

func Simple_Statement_3(x, y int, a, _ float64) float64 { //or a float64, _ float64
	return float64(x*y) + a
}

func main() {
	fmt.Printf("%T\n", Standard_Statement)
	fmt.Printf("%T\n", Simple_Statement_1)
	fmt.Printf("%T\n", Simple_Statement_2)
	fmt.Printf("%T\n", Simple_Statement_3)
}

输出结果如下,可见4种声明方式本质上相同: image.png

以上演示的是有返回值的函数,无返回值只需去掉返回列表即可。

此外需要注意的是Go语言不支持函数默认参数,圣经中陈述为“每一次函数调用都必须按照声明顺序为所有参数提供实参(参数值)”,否则会出现如下问题: image.png

多返回值函数

熟悉C语言就知道C的函数不能做到返回多个值,如果需要实现类似的功能,本人常用的方法是引用传递、全局变量或返回聚合型如结构体等实现(如有更多方法请告诉我)。

但是Go语言中支持函数返回多个参数。例如许多标准库函数,除了返回应有的计算结果外,还会返回一个bool值表示出错时的错误信息,见下例中strconv包中的函数:

package main

import (
	"fmt"
	"strconv"
)

func main() {
	re_data, err := strconv.ParseInt("13579", 10, 64)    //参数列表:字符串,进制,返回类型
	fmt.Println(re_data, err)
}

输出如下: image.png

上述函数执行中没有错误,故返回nil,但是主函数中可以用变量err接收表示确实有这个返回值存在。

除此之外,函数中return语句带多个参数实现多参数返回,声明中的返回参数列表也需要有对应的多个参数,具体见下例:

package main

import "fmt"
import "strconv"

func Date_BreakDown(s string) (year, month, day int64, err error) {
	year, err = strconv.ParseInt(s[:4], 10, 32)
	month, err = strconv.ParseInt(s[4:6], 10, 32)
	day, err = strconv.ParseInt(s[6:], 10, 32)
	return year, month, day, err
}

func main() {
	var Date string
	fmt.Println("Input a Date (year+month+day,example 20230201)")
	fmt.Scan(&Date)
	fmt.Println(Date_BreakDown(Date))
}

以上是一个日期分解函数,函数需要同时返回年/月/日和错误四个参数。运行结果如下: image.png

递归函数

递归函数只是函数中调用自身的一种使用方式,并没有过多特别的用法,下例是递归计算阶乘的例子:

package main

import "fmt"

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

func main() {
	var n int
	fmt.Scan(&n)
	fmt.Println(Factorial(n))
}

运行结果如下: image.png

可变参数

可变参数指的是参数数量可变,而非参数类型。使用方法为在参数列表最后一个参数的类型后加...,表示可以接收任意个数个该类型的参数。

具体见下例,求任意个数参数之和(理解语法即可,不再演示运行结果):

func Cal_Sum(vals ...int) int {
    total := 0
    for _, val := range vals {
        total += val
    }
    return total
}

本篇主要介绍函数,包括函数声明、多返回值、递归和可变参数的使用。本篇将是Go语言基础篇的最后一篇,后续将继续跟进进阶篇,更多聚焦Go语言工程实践中的使用