阅读本文前,建议已掌握基本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)替代。
不出意料运行结果应该相同:
可以使用占位符%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种声明方式本质上相同:
以上演示的是有返回值的函数,无返回值只需去掉返回列表即可。
此外需要注意的是Go语言不支持函数默认参数,圣经中陈述为“每一次函数调用都必须按照声明顺序为所有参数提供实参(参数值)”,否则会出现如下问题:
多返回值函数
熟悉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)
}
输出如下:
上述函数执行中没有错误,故返回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))
}
以上是一个日期分解函数,函数需要同时返回年/月/日和错误四个参数。运行结果如下:
递归函数
递归函数只是函数中调用自身的一种使用方式,并没有过多特别的用法,下例是递归计算阶乘的例子:
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))
}
运行结果如下:
可变参数
可变参数指的是参数数量可变,而非参数类型。使用方法为在参数列表最后一个参数的类型后加...,表示可以接收任意个数个该类型的参数。
具体见下例,求任意个数参数之和(理解语法即可,不再演示运行结果):
func Cal_Sum(vals ...int) int {
total := 0
for _, val := range vals {
total += val
}
return total
}
本篇主要介绍函数,包括函数声明、多返回值、递归和可变参数的使用。本篇将是Go语言基础篇的最后一篇,后续将继续跟进进阶篇,更多聚焦Go语言工程实践中的使用