1. 函数定义和调用
函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码块,其可以提高应用的模块性和代码的重复利用率。Go 语言函数与其他语言函数最大的不同是,Go 语言的函数可以支持返回任意多个值,而其他语言的函数一般只支持返回一个值。Go 语言的函数支持普通函数、匿名函数和闭包三种形式。函数的基本组成为:func关键字、函数名、参数列表、返回值、函数体和返回语句,一个Go程序至少包含一个main函数,函数是最基本的代码块。
1.1. 普通函数定义
普通函数定义语法格式:
func funcName(parametername type1, parametername type2) (val returnType1, val returnType2) {//函数体return value1, value2 //返回多个值}
注:Go函数和其他语言的函数定义最明显的区别就是,可以返回多个值,所以返回值列表中需声明多个返回值类型(可以不声明返回值变量)。如果函数返回一个无名变量或者没有返回值,返回值列表可以省略。如果只有一个返回值且不声明返回值变量,返回值列表的括号可以省略。
示例:
func returnTwoNumber(num1 int, num2 int) (int, int){// 原样返回传入的两个值return num1, num2}
1.2. 函数调用
函数在定义后就可被调用(无需像C语言在使用前进行前置声明),函数内的局部变量只能在函数体内使用,函数调用结束后,局部变量会被释放失效。
函数调用格式:返回值变量列表 = 函数名(实参列表)
示例:
package mainimport "fmt"func main() {var res1 intvar res2 int// 函数调用res1, res2 = returnTwoNumber(1, 2)fmt.Println(res1, res2)}func returnTwoNumber(num1 int, num2 int) (int, int) {// 原样返回传入的两个值return num1, num2}
1.3. 拓展
- Go语言函数借鉴了很多动态语言的优点,如:
- 无须前置声明
- 不支持命名嵌套定义(nested)
- 不支持同名函数重载(overload)
- 不支持默认参数
- 支持不定长变参
- 支持多返回值
- 支持命名返回值
- 支持匿名函数和闭包
函数属于第一类对象,具备相同签名(形参列表和返回值列表的类型相同)的两个函数被视作同一类型。
第一类对象(first-class object)指可在运行期创建,可用作函数参数或返回值,可存入变量的实体。最常见的用法就是匿名函数。
建议函数命名规则
- 通常是动词和介词加上名词,比如
scanWords - 避免不必要的缩写,比如
printError要比printErr更好 - 避免使用类型关键字,比如
buildUserStruct看上去会很别扭 - 避免歧义,不能有多种用途造成误解
- 避免只能通过大小写区分的同名函数
- 避免与内置函数同名,会导致误用
- 避免使用数字,除非是特定专有名词
- 避免添加作用域提示前缀
统一使用
camel/pascal case拼写风格camel case:骆驼拼写法,依靠单词的大小写拼写复合词的做法,”骆驼拼写法”又分为两种。第一个词的首字母小写,后面每个词的首字母大写,叫做”小骆驼拼写法”(lowerCamelCase);第一个词的首字母,以及后面每个词的首字母都大写,叫做”大骆驼拼写法”(UpperCamelCase),又称”帕斯卡拼写法”(PascalCase)。使用相同术语,保持一致性
- 使用习惯用语,比如
init表示初始化,is/has返回布尔值结果 使用反义词命名行为相反的函数,比如
get/set,min/max等2. 函数的参数
2.1. 普通参数
Golang中函数的参数,为形式参数,是局部变量,只能在函数内使用,传递方式为值传递,即传递的参数其实是实际参数的一份拷贝,而不是真正的实际参数。
在 Go 语言中,如果相邻的形参类型相同,可以省略前几个参数的类型,只需要写最后一个参数的类型即可。// 省略前几个形参的类型,三个参数的类型都为paramTypefunc funcName(param1, param2, param3 paramType)(returnVal returnType){return 返回值列表}
2.2. 可变参数
可变参数:可变参数函数是指一个函数拥有不定引数,即是它接受一个可变数目的参数。简单来说,就是函数的参数个数可变,参数类型不定的函数。
在C语言时代大家一般都用过 printf() 函数,从那个时候开始其实已经在感受可变参数的魅力和价值,如同C语言中的 printf() 函数,Go语言标准库中的 fmt.Println() 等函数的实现也依赖于语言的可变参数功能。
合适地使用可变参数,可以让代码简单易用,尤其是输入输出类函数,比如日志函数等。
