前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go基础系列 | 10. 函数

Go基础系列 | 10. 函数

原创
作者头像
潇洒哥和黑大帅
修改2021-08-10 10:38:24
3690
修改2021-08-10 10:38:24
举报
文章被收录于专栏:WebDeveloperWebDeveloper

选自“潇洒哥和黑大帅”公众号,一个有爱情的程序员公众号,可以在文章末扫码关注。

学到什么

  1. 如何调用函数?
  2. 如何构造函数?
  3. 函数如何返回多个值?
  4. 如何构造匿名函数?
  5. 如何传递函数?
  6. 内置函数有哪些?

介绍

函数是基本的代码块,它负责将一个复杂问题分解为不同的函数提供调用与复用。

编写函数时,无需关注顺序,因为 Go 语言是编译型的。

在 Go 语言中有三种函数类型:

  • 基本格式:有命名的函数,直接调用完事。
  • 匿名函数:没有名字的函数。
  • 结构体携带的函数:也可以称之为方法,后续结构体再展开讲解。

基本格式

代码语言:txt
复制
func Fun1(arg1 T, arg2 T) T {
		...
		return r1
}
  • Fun1 为自定义的函数名称。
  • arg1arg2 为自定义参数名称,声明了两个参数,可以再增加。
  • T 代表 Go 语言中的任意类型,使用时替换成 int、string、slice 等等类型。
  • 小括号后紧跟函数返回值类型。
  • return 为函数返回的关键字,携带要返回的值,函数内之后的逻辑将不会执行。
  • 函数体的第一个花括号必须紧跟在函数后。

举例:

代码语言:txt
复制
// 计算两个数之和并且返回
func AddNum(n1 int, n2 int) int {
	return n1 + n2
}

函数也可以没有返回值,这个时候就无需 return 关键字,例如: main() 入口函数、 init() 初始化函数。

当函数体内出现了 panic 函数,用于抛出异常,这时如果定义了返回类型, return 关键字就可以选择省略。

返回多个值

Go 语言函数中有个特点,可以多个值返回。在声明返回值类型时,可以不指定名称,也可以指定名称,啥意思呢,往下看。

1. 无名称

代码语言:txt
复制
func Fun1(arg1 T, arg2 T) (T, T) {
		...
		return r1, r2
}

和“基本格式”的不同点:

  • 当需要返回至少两个值时,返回类型需要用小括号包裹,以逗号分隔。
  • 使用 return 携带多个返回值。

2. 有名称

代码语言:txt
复制
func Fun1(arg1 T, arg2 T) (n1 T, n2 T) {
		...
		return
}
  • 返回值类型指定了名称后,在 return 返回时,可以不带值,当然也可以都带上。
  • 当有了名称,即使是 1 个返回类型,也需要用小括号包裹。

为什么有了名称 return 就不用携带值呢?

因为相当于在返回时,初始化好了返回值,例如上面的格式中 n1n2 就是初始化的两个变量,在函数运算中,只要将返回结果存入 n1n2 中,不存就按照初始化返回,当然也可以 return 携带值。

函数调用

构造好一个函数后,如何调用,格式如下:

代码语言:txt
复制
r1, r2 := Fun1(param1, param2)

调用时传递了两个参数,返回时接受两个返回值。

如果接受多个值时,某个值我不想使用时,是不能搁置在那的,不然编译器会报错,需要使用下划线 "_" 替代,表示我不用。

代码语言:txt
复制
r1, _ := Fun1(param1, param2)

匿名函数

匿名函数就是在构造函数时,函数没有名称,想调用时,需要把匿名函数赋值给一个变量,或者在构造时直接调用。

1. 赋值给变量

代码语言:txt
复制
fun1 := func (arg1 T, arg2 T) T {
		...
		return r1
}

赋值后, fun1 就是一个函数类型的变量, 调用格式:fun1(param1, param2)

2. 构造时调用

代码语言:txt
复制
func (arg1 T, arg2 T) T {
		...
		return r1
}(param1, param2)

在构造函数时,花括号后紧跟参数传递(param1, param2),不需要赋值给一个变量,直接构造后马上调用。

传递函数

在 Go 语言中,函数是“一等公民”,它和 int 、string 等等,都是一个级别,可以作为参数进行传递。

举例:

代码语言:txt
复制
// function/deliver.go

package main

// callback 是一个函数类型参数
func Calc(callback func(n1 int, n2 int) int) int {
	x, y := 3, 4
	return callback(x, y)
}

// 计算两数之积
func Mul(n1 int, n2 int) int {
	return n1 * n2
}

func main() {
	// 第一个:传递一个匿名函数
	Calc(func(n1 int, n2 int) int {
		return n1 + n2
	})

	// 第二个:传递一个定义好的函数
	Calc(Mul)
}

分别演示了两种函数的传递方式,第一个匿名函数计算两数之和,第二个用定义好的函数计算两数之积。当然传递函数不止是通过参数,也可以是函数返回值、切片元素保存、map值保存等等。

声明函数类型

声明函数类型,意思就是可以自定义一个函数类型,给这个函数取一个别名,像例如 int 一样很方便的去声明变量或者参数类型。

代码语言:txt
复制
type CallbackFunc func(n1 int, n2 int) int

现在自定义了一个名为 CallbackFunc 的函数类型,下来看如何使用:

代码语言:txt
复制
func Calc(callback CallbackFunc) int {
...
}

Calc 函数有一个函数参数,这个参数的类型名称为 CallbackFunc

函数参数

1. 参数类型省略

在声明函数参数时,有时候会遇到连续声明多个相同类型,这个时候,就可以只保留一个类型名称。

代码语言:txt
复制
// 没精简的
func Fun1(arg1 string, arg2 int, arg3 int)

// 精简后
func Fun1(arg1 string, arg2, arg3 int)

精简后, arg2 参数后省略了 int,这样就和它后面的参数类型一致。

2. 值传递与引用传递

我们先定下参数称呼,函数调用时传递的参数称为实参,构造函数时的参数称为形参。

在 Go 语言中,切片(slice)、map、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递,在函数内修改形参是会改变实参的值。

对于切片,有种情况会打破引用传递这个规律,具体可以看看 《内置结合 - 切片》这篇文章。

对于其它剩下的类型,默认都是值传递,函数接收到的形参只是副本,函数内对形参的更改是不会影响到实参的。

如果希望更改实参的值,可以传递指针,在实参前增加“&”符号,表示取实参的地址,例如: Fun1(&param)

3. 变长参数

当构造函数时,函数的最后一个参数是 ...T 形式时,称为变长参数,它可以接受至少 0 个数据。

代码语言:txt
复制
// 一个固定参数,一个变长参数
// nums 实际是一个切片
func Func1(str string, nums ...int) {
	...
}

调用例子如下:

代码语言:txt
复制
// 没传递变长参数
Func1("miao")

// 给变长参数传递不同数量的值
Func1("miao", 1)
Func1("miao", 1, 2)

当把一个切片类型传递给可变参数时,在切片后跟着 ... 三个点,传递给变长参数,表示将切片元素展开。

代码语言:txt
复制
nums := []int{1, 2, 3}
Func1("miao", nums...)

内置函数

在 Go 语言中,有一些函数无需导入任何包就可以使用,下来对这些函数简要说明一下。

总共 15 个内置函数,如下:

  1. make:为切片,map、通道类型分配内存并初始化对象。
  2. len:计算数组、切片、map、通道的长度。
  3. cap:计算数组、切片、通道的容量。
  4. delete:删除 map 中对应的键值对。
  5. append:将数据添加到切片的末尾。
  6. copy:将原切片的数据复制到新切片中。
  7. new:除切片、map、通道类型以外的类型分配内存并初始化对象,返回的类型为指针。
  8. complex:生成一个复数。
  9. real:获取复数的实部。
  10. imag:获取复数的虚部
  11. print:将信息打印到标准输出,没有换行。
  12. println:将信息打印到标准输出并换行。
  13. close:关闭通道。
  14. panic:触发程序异常。
  15. recover:捕捉 panic 的异常信息。

总结

本篇我对 Go 语言中的函数进行了系统的讲解,也列举了 15 个内置函数。对于内置函数的使用,有的在前面文章使用过,有的还没有,先做一个整体的了解,等到了用的时候再详查。

如果有遇到不懂的就在下方留言,不要和我客气!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 学到什么
  • 介绍
  • 基本格式
  • 返回多个值
    • 1. 无名称
      • 2. 有名称
      • 函数调用
      • 匿名函数
        • 1. 赋值给变量
          • 2. 构造时调用
          • 传递函数
          • 声明函数类型
          • 函数参数
            • 1. 参数类型省略
              • 2. 值传递与引用传递
                • 3. 变长参数
                • 内置函数
                • 总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档