Golang教程:函数、变参函数
函数是完成一个特定任务的代码块。一个函数接受输入,对输入进行一些运算并产生输出。
函数声明
在 Go 中声明一个函数的语法为:
func functionname(parametername type) returntype {
//function body
}
函数声明以关键字 func 开头,后面是函数名字,接着是在 ( 和 ) 之间指定的参数列表,然后是函数的返回类型。指定参数的语法为参数名称后面跟着参数类型。可以指定任意数量的参数,形式为: (parameter1 type, parameter2 type)。最后是由 { 和 } 以及它们之间的代码块组成的函数体。
在一个函数中,参数和返回值是可选的。因此下面的语法也是合法的函数声明:
func functionname() {
}
函数的例子
让我们写一个函数,它以单个产品的价格和产品数量作为输入参数,并以总价格(单个产品的价格与产品数量的乘积)作为返回值。
func calculateBill(price int, no int) int {
var totalPrice = price * no
return totalPrice
}
上面的函数接受两个 int 类型的输入参数:price 和 no,并返回 totalPrice(price 与 no 的乘积) 。返回值的类型也是 int。
如果连续的参数具有相同的类型,我们可以避免每次都写出它们的类型,只需要在结束的时候写一次就可以了,比如:price int, no int 可以写成:price, no int。 于是上面的函数可以写成:
func calculateBill(price, no int) int {
var totalPrice = price * no
return totalPrice
}
我们已经定义好了我们函数,现在让我们在代码中调用它。调用函数的语法为:functionname(parameters)。上面定义的函数 calculateBill 可以通过下面的代码调用:
calculateBill(, )
下面是完整的程序,它调用 calculateBill 并计算总价格。
package main import (
"fmt"
) func calculateBill(price, no int) int {
var totalPrice = price * no
return totalPrice
}
func main() {
price, no := ,
totalPrice := calculateBill(price, no)
fmt.Println("Total price is ", totalPrice)
}
多个返回值
一个函数可以返回多个值。让我们写一个函数 rectProps,它接受一个矩形的长和宽,并返回该矩形的面积和周长。矩形的面积为长与宽的积。周长为长与宽的和的 2 倍。
package main import (
"fmt"
) func rectProps(length, width float64)(float64, float64) {
var area = length * width
var perimeter = (length + width) *
return area, perimeter
} func main() {
area, perimeter := rectProps(10.8, 5.6)
fmt.Printf("Area %f Perimeter %f", area, perimeter)
}
如果一个函数有多个返回值,那么这些返回值应该用小括号()括起来,比如:func rectProps(length, width float64)(float64, float64) 接受两个类型为 float64 的参数(length 和 width),并且同样返回两个类型为 float64 的返回值。上面程序的输出为:Area 60.480000 Perimeter 32.800000
具名返回值
可以给一个函数的返回值指定名字。如果指定了一个返回值的名字,则可以视为在该函数的第一行中定义了该名字的变量。
上面的 rectProps 函数可以用具名返回值的形式重写如下:
func rectProps(length, width float64)(area, perimeter float64) {
area = length * width
perimeter = (length + width) *
return //no explicit return value
}
在上面的函数中,area 和 perimeter 是具名返回值。注意 return 语句没有指定任何返回值。因为在函数声明时已经指定area 和 perimeter 是返回值,在遇到 return 语句时它们会自动从函数中返回。
空指示符
在 Go 中,下划线(_)表示空指示符(blank identifier)。它可以用于代替任何类型的任何值。让我们看看如何使用空指示符。
我们知道上面定义的函数 rectProps 返回矩形的面积(area)和周长(perimeter)。如果我们只需要获取 area 而想要忽略 perimeter该怎么办呢?这时候就可以使用空指示符。
下面的程序仅接收 rectProps 返回的 area:
package main import (
"fmt"
) func rectProps(length, width float64) (float64, float64) {
var area = length * width
var perimeter = (length + width) *
return area, perimeter
}
func main() {
area, _ := rectProps(10.8, 5.6) // perimeter is discarded
fmt.Printf("Area %f ", area)
}
在 area, _ := rectProps(10.8, 5.6) 这一行,我们仅仅获取了 area,而使用空指示符 _ 来忽略第二个返回值(perimeter)。
什么是变参函数?
变参函数是指可以接受可变数量的参数的函数。
语法
如果一个函数的最后一个参数由 ...T 表示,则表示该函数可以接受任意数量的类型为 T 的参数。
请注意只有函数的最后一个参数才能指定为可变参数。
例子
你有没有想过为什么 append 函数可以将任意数量的值追加到切片末尾?这是因为它是一个变参函数。append 的原型为 func append(slice []Type, elems ...Type) []Type,其中 elems 是一个可变参数。
让我们来创建一个自己的变参函数。我们将编写一个程序来判断某个特定整数是否包含在某个整数列表中。
package main import (
"fmt"
) func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
found := false
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
found = true
}
}
if !found {
fmt.Println(num, "not found in ", nums)
}
fmt.Printf("\n")
}
func main() {
find(, , , )
find(, , , , , )
find(, , , )
find()
}
上面的程序中,func find(num int, nums ...int) 可以接受任意数量的参数。...int 在内部表示为切片。在这里 nums的类型为 []int。
第 10 行利用 range for 遍历 nums 切片,如果找到 num 则打印 num 所在位置,否则打印没有找到。
上面的程序输出如下:
type of nums is []int
found at index in [ ] type of nums is []int
found at index in [ ] type of nums is []int
not found in [ ] type of nums is []int
not found in []
在第 25 行,find 只有一个参数。我们没有传递任何参数给 nums ...int。这是合法的,(译者注:如果没有给可变参数传递任何值,则可变参数为 nil 切片),在这里 nums 是一个 nil 切片,长度和容量都是0。
传递切片给可变参数
我们已经提到 ...T 在内部表示为类型是 []T 切片。如果真是这样,可以传递一个切片给可变参数吗?让我们从下面的例子中寻找答案:
package main import (
"fmt"
) func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
found := false
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
found = true
}
}
if !found {
fmt.Println(num, "not found in ", nums)
}
fmt.Printf("\n")
}
func main() {
nums := []int{, , }
find(, nums)
}
在第 23 行,我们没有将若干数量的参数传递给 find 的最后一个参数, 而是传递了一个切片。这是非法的,我们不能传递一个切片给可变参数。上面的程序将报错:main.go:23: cannot use nums (type []int) as type int in argument to find。
这里有一个语法糖可以用来将切片传递给变参函数。可以在切片后面加 ...,这样会将切片展开为其中的各个元素并将它们传递给变参函数。这样该程序将正常工作。
上面的程序如果将第23行的 find(89, nums) 改为 find(89, nums...),程序将通过编译,并输出如下:
type of nums is []int
found at index in [ ]
Golang教程:函数、变参函数的更多相关文章
- Golang简单入门教程——函数进阶篇
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第八篇,我们来聊聊golang当中的函数. 我们在之前的时候已经介绍过了函数的基本用法,知道了怎么样设计或者是定义一 ...
- golang的函数
在golang中, 函数是第一类值(first-class object), 即函数可以赋值与被赋值. 换言之, 函数也可以作为ReceiverType, 定义自己的method. 实例: http. ...
- golang(06)函数介绍
原文链接 http://www.limerence2017.com/2019/09/11/golang11/#more 函数简介 函数是编程语言中不可缺少的部分,在golang这门语言中函数是一等公民 ...
- golang笔记——函数与方法
如果你遇到没有函数体的函数声明,表示该函数不是以Go实现的. package math func Sin(x float64) float //implemented in assembly lang ...
- Golang教程:数组和切片
数组 数组是类型相同的元素的集合.例如,整数 5, 8, 9, 79, 76 的集合就构成了一个数组.Go不允许在数组中混合使用不同类型的元素(比如整数和字符串). 声明 var variable_n ...
- Golang tips ----- 函数
1.在函数调用时,Golang没有默认参数值 2.一个函数声明如果没有函数体,表面该函数不是由Golang实现的,这样的声明定义了函数标识符 3.拥有函数名的函数只能在包级语法块中被声明 4.函数值( ...
- golang 原子操作函数
golang中的原子操作在sync/atomic package中. 下文以比较和交换操作函数为例,介绍其使用. CompareAndSwapInt32 比较和交换操作是原子性的. // Compar ...
- Golang之函数练习
小例题: package main import "fmt" /* 函数练习, 可变参数使用 写一个函数add 支持1个或多个int相加,并返回相加结果 写一个函数concat,支 ...
- [golang note] 函数定义
普通函数定义 √ golang函数基本组成:关键字func.函数名.参数列表.返回值.函数体和返回语句. • 语法如下 func 函数名(参数列表) (返回值列表) { // 函数体 } • 示例如下 ...
随机推荐
- org.apache.catalina.util.DefaultAnnotationProcessor cannot be cast to org.ap解决方案
非常可能是因为tomcat的lib文件夹jar包和项目的lib文件下的jar包冲突了 把项目下lib文件下和tomcat的jar的重复的全部删除. 注意,如果你是先建flex工程然后转成web形式的, ...
- ASP.NET MVC 如何使用自定义过滤器(筛选器)
继承*****Attribute(筛选器三种具体类)-->重写方法-->标记在控制器 或者 方法上面 或者 在FilterConfig中Add [类名(类属性 = 值)]还有[AllowA ...
- centos7 守护进程
ASP.NET Core应用程序发布linux在shell中运行是正常的.可一但shell关闭网站也就关闭了,所以要配置守护进程, 用的是Supervisor,本文主要记录配置的过程和过程遇到的问题 ...
- ES6——介绍
什么是ES6? ECMAScript 6.0 (简称ES6)是继ECMAScript 5.1 之后 JavaScript 语言的下一代标准,发布在2015年6月.他的目标,是使得 JavaScript ...
- form表单 相同name 多个value 的后台接受问题
使用ajax序列化传到后台. data : $("#formid").serialize(); public void fun(@Valid Vo vo){} 使用vo的数组字段属 ...
- javascript滚动到大于一定距离显示隐藏
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ZJOI round1游记
Day 0 到镇海报道了 大佬们太多了--话说镇海的晚饭还真好吃啊-- 听说某人要咱去找bwh--不过咱和他也不是很熟啊--还是算了吧--(才不是因为嫌麻烦懒得去呢) 晚上吃完晚饭之后在镇海校园里参观 ...
- TensorFlow支持GPU配置问题
目录 Tensorflow-GPU 环境条件 现有硬件 现有软件 硬件要求 软件要求 步骤 0.Visual studio 1.下载安装显卡驱动 2.下载对应版本 CUDA 3.安装配置 cuDNN ...
- ArchLinux中证书错误解决方案
ca-certificates 更新 x509: failed to load system roots and no roots provided. curl error: Problem with ...
- jxl读取excel
String path=""; String path2=""; File file = new File(path); File file2 = new Fi ...