Go语言函数详解
函数
(1)函数的定义
- 函数使用func进行定义
- 函数是基本的代码块,用于执行一个任务
- Go语言至少有一个main函数
- 函数声明告诉了编译器函数的名称,返回类型和参数
//1.无参数无返回值函数的定义
func test1(){
fmt.Println("无参数无返回值函数的定义\n")
}
//2.有参数无返回值函数的定义
func test2(str string){
fmt.Println("有参无返回值:%s\n",str)
}
//3.多参无返回值
func test3(a,b int) int{
return a+b
}
//4.多个返回值
func test4(a,b int) (int,int){
return a,b
}
//函数的调用
fun main()
{
test1()
test2("WY")
test3(1,2)
test4(5,6)
}
(2)函数的可变参数
- 一个函数的参数类型确定,但个数不确定时可以使用可变参数
- 定义可变参数时,使用**... **符号
- 可变参数本质上是保存到了一个数组当中
- 注意:可变参数要放在参数定义的最后;一个函数的参数列表最多只有一个可变参数
//可变参数函数定义
func add_sum(num...int){
sum := 0
for _,i := range num{
sum += num[i-1]
}
}
(3)参数传递的类型
参数分为两种类型:
- 值类型-操作的是数据本身,例如我们常用的:int,string,bool,float64,array
- 引用类型的数据-操作的是数据的地址:例如slice,map,chan
值传递在调用完函数后不会修改原本值传递参数的值
//定义一个函数,进行值传递实验
func update(arr2 [4]int){
fmt.Println("arr2接收到的数据:"arr2)
arr2[0] = 100
fmt.Println("arr2修改后的数据:"arr2)
}
//定义主函数,调用update进行值传递观察
func main(){
arr := [4]int{1,2,3,4} //定义一个数组
fmt.Println(arr)
//传递值
update(arr)
fmt.Println("调用后的数据") //这里的结果为[1,2,3,4]
}
- 引用类型数据的参数传递在调用完函数后会修改原本值传递参数的值
package main
import "fmt"
/*
=====引用传递=======
1、定义一个切片
2、通过方法修改切片里面的数据
3、打印输出修改后值
*/
func main() {
arr := []int{1, 2, 3, 4} //定义一个切片
fmt.Println("调用修改前的数据", arr)
updata2(arr)
fmt.Println("调用修改后的数据", arr)
}
func updata2(arr []int) {
fmt.Println("arr接受的数据:", arr)
arr[0] = 100
fmt.Println("arr修改后的数据:", arr)
}
/*
调用修改前的数据 [1 2 3 4]
arr接受的数据: [1 2 3 4]
arr修改后的数据: [100 2 3 4]
调用修改后的数据 [100 2 3 4]
*/
(4)函数变量的作用域
- 作用域:变量可以使用的范围
- 局部变量:函数内部定义的变量,叫做局部变量,只能在定义该变量的函数内使用
- 全局变量:函数外部定义的变量,叫做全局变量,可以在任何函数里面使用
package main
import "fmt"
// 全局变量 所有函数都可以使用
var num int = 30
func main() {
// 局部变量 temp 只能在定义temp的方法中使用
temp := 100
if b := 1; b < 10 {
temp := 30
fmt.Println("局部变量b:", b)
fmt.Println("局部变量temp:", temp)
}
fmt.Println(temp)
// 调用f1,f2方法
f1()
f2()
}
func f1() {
fmt.Println(num)
}
func f2() {
fmt.Println(num)
}
(5)递归函数
- 递归函数的定义:可以自己调用自己的函数
- 递归函数必须要有一个出口,否则会陷入死循环
package main
import "fmt"
/*
1、创建一个求和函数 getsum
2、给递归函数一个出口
3、创建对象来接收函数
*/
func main() {
//3、创建对象来接收函数
sum := getSum(5)
fmt.Println(sum)
}
//1、创建一个求和函数 getsum
func getSum(n int) int {
//2、给递归函数一个出口
if n == 1 {
return 1
}
return getSum(n-1) + n
}
(6) defer延迟函数
- defer函数可以延迟一个函数的执行
在以下代码块中,控制台打印的结果是1 2 4 3,因为defer将f(3)延迟到最后执行了
package main
import "fmt"
func main() {
f("1")
f("2")
defer f("3") //将该函数延迟到最后执行
f("4")
}
func f(s string) {
fmt.Println(s)
}
- 如果使用了多个defer语句,则函数执行到最后时,这些defer语句会按照逆序执行
package main
import "fmt"
func main() {
f("1")
f("2")
defer f("3")
f("4")
defer f("5")
f("6")
defer f("7")
f("8")
}
func f(s string) {
fmt.Println(s)
}
/*
输出结果:
1
2
4
6
8
7
5
3
*/
(7)func数据类型详解
在go语言中,函数是复合类型,本质上可以看作是一个特殊的变量
func本身就是一个数据类型,func定义的函数之间可以相互赋值
package main
import "fmt"
/*
fun本身就是一个数据类型
1、创建一个函数
2、在mian方法定义相同类型的函数
3、将定义后的函数赋值个另一个函数
*/
func main() {
//2、在mian方法定义相同类型的函数
var fg func(int, int)
//3、将定义后的函数赋值个另一个函数
fg = ff //将fg函数定义为ff函数相同的功能
fg(1, 2) //最后输出的结果为 1 2
}
//1、创建一个函数
func ff(a, b int) {
fmt.Println(a, b)
}
(8)匿名函数
- 什么是匿名函数:匿名函数就是没有名字的函数
匿名函数的创建
//这就是一个匿名函数,但如果直接放在代码块中不调用则编译器会报错
func() {
fmt.Println("匿名函数")
}
//带参匿名函数
func(a,b int){
fmt.Println("带参匿名函数")
}
//带参且具有返回值函数
func(a,b int) int{
fmt.Println("带参和返回值匿名函数")
return a+b
}
匿名函数多种调用方式
func main(){
//方式1:用一个变量调用匿名函数
f3 := func(){
fmt.Println("匿名函数的调用方式1")
}
f3() //调用匿名函数
//方式2:创建匿名函数后直接调用func(),在{}后直接添加()进行调用
func(){
fmt.Println("匿名函数调用方式2")
}()
//带参匿名函数的调用
func(a,b int){
fmt.Println("带参匿名函数调用")
}(1,2)
//带参和返回值匿名函数调用
f5 := func(a,b int) int{
fmt.Println("带参和返回值匿名函数")
return a+b
}(1,2)
fmt.Println(f5) //打印调用结果
}
(9)高阶函数和回调函数
回调函数:将一个函数作为另一个函数的参数
若将fun1函数作为fun2函数的参数,则fun2叫做高阶函数,fun1称为回调函数
package main
import "fmt"
//1、创建一个高阶函数oper,传如一个函数类型的参数且有返回值
func oper(a, b int, fun func(int, int) int) int {
r2 := fun(a, b)
return r2
}
//2.创建其他方法的函数
func add(a, b int) int {
return a + b
}
//创建其他方法的函数
func sub(a, b int) int {
return a - b
}
func main() {
r1 := add(1, 2)
fmt.Println(r1)
//3、调用高阶函数时,传入其他方法的函数
r3 := oper(3, 4, add)
fmt.Println(r3)
r4 := oper(8, 4, sub)
fmt.Println(r4)
}
(10)闭包
- 一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量并且该外层函数的返回值就是这个内层函数。
- 这个内层函数和外层函数的局部变量,统称为闭包结构。
- 局部变量的生命周期就会发生改变,正常的局部变量会随着函数的调用而创建,随着函数的结束而销毁但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还在继续使用
package main
import "fmt"
// 定义一个闭包函数。func() int是局部变量和返回值fun的类型
func increment() func() int {
//局部变量
i := 0
//定义一个匿名函数 给变量自增并返回
fun := func() int {
//内层函数,没有执行
i++
return i
}
return fun
}
func main() {
//定义一个变量 接受返回值(函数)
r1 := increment() //创建函数
fmt.Println(r1) //这里打印的是地址,因为r1还没有执行
v1 := r1()
fmt.Println(v1)
//不断调用自增+1
v2 := r1()
fmt.Println(v2)
//不断调用自增+1
fmt.Println(r1())
fmt.Println(r1())
fmt.Println(r1())
fmt.Println(r1())
fmt.Println("====================")
// ==========================================================
r2 := increment() //创建函数,i也会清零
v3 := r2()
fmt.Println(v3)
fmt.Println(r2())
fmt.Println(r2())
fmt.Println(r2())
fmt.Println(r1()) //这里调用的是r1,因此i值还是原来r1的i值,这里自增后为7
fmt.Println(r2())
}
/*
输出结果:
0xd5ea00
1
2
3
4
5
6
====================
1
2
3
4
7
5
*/
Go语言函数详解的更多相关文章
- 【C语言】printf函数详解
C语言printf函数详解 一.相关基础知识 请求printf()打印变量的指令取决于变量的类型,例如打印整数用%d符号,打印字符用%c符号,这些符号称为转换说明(conversion specifi ...
- 【转载】C语言itoa()函数和atoi()函数详解(整数转字符C实现)
本文转自: C语言itoa()函数和atoi()函数详解(整数转字符C实现) 介绍 C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. int/float to ...
- C语言memset函数详解
C语言memset函数详解 memset() 的作用:在一段内存块中填充某个给定的值,通常用于数组初始化与数组清零. 它是直接操作内存空间,mem即“内存”(memory)的意思.该函数的原型为: # ...
- Netsuite Formula > Oracle函数列表速查(PL/SQL单行函数和组函数详解).txt
PL/SQL单行函数和组函数详解 函数是一种有零个或多个参数并且有一个返回值的程序.在SQL中Oracle内建了一系列函数,这些函数都可被称为SQL或PL/SQL语句,函数主要分为两大类: 单行函数 ...
- loadrunner 脚本开发- web_url函数详解
脚本开发- web_url函数详解 by:授客 QQ:1033553122 加载指定url的web页面(GET请求) C语言函数 int web_url( const char *StepName ...
- 深入理解C语言 - 指针详解
一.什么是指针 C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址.CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位.这里,数据对象是指存储在 ...
- CString 的成员函数详解
CSTRING的成员函数详解 typedef ATL::CStringT< TCHAR, StrTraitMFC_DLL< TCHAR > > CString;CStrin ...
- malloc 与 free函数详解<转载>
malloc和free函数详解 本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...
- NSSearchPathForDirectoriesInDomains函数详解
NSSearchPathForDirectoriesInDomains函数详解 #import "NSString+FilePath.h" @implementation ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
随机推荐
- 重要变更 | Hugging Face Hub 的 Git 操作不再支持使用密码验证
在 Hugging Face,我们一直致力于提升服务安全性,因此,我们将对通过 Git 与 Hugging Face Hub 交互时的认证方式进行更改.从 2023 年 10 月 1 日 开始,我们将 ...
- CodeForces 1324F Maximum White Subtree
题意 给定一棵\(n\)个节点的无根树,每个节点为黑色或者白色,每个点的答案为包含该点的子树(指无根子树)的白色节点数减黑色节点数的最大值 分析 对于无根树的题一般指定某一个点为根,不妨设为\(1\) ...
- 深入理解Linux内核——内存管理(4)——伙伴系统(1)
提要:本系列文章主要参考MIT 6.828课程以及两本书籍<深入理解Linux内核> <深入Linux内核架构>对Linux内核内容进行总结. 内存管理的实现覆盖了多个领域: ...
- JSTL fn函数使用总结
首先,我们要在页面的最上方引用: <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/function ...
- No manual entry for ls终极解决办法
No manual entry for ls解决办法,最后一种方法一定能解决你的问题 步骤一:确认man是否已经安装 #which man /usr/bin/man---返回此行,证明已经安装 步骤二 ...
- [EasyExcel] 导出合并单元格
前言 使用spring boot 对excel 进行操作在平时项目中要经常使用.常见通过jxl和poi 的方式进行操作.但他们都存在一个严重的问题就是非常的耗内存.这里介绍一种 Easy Excel ...
- MySQL的字段数量以及长度限制
一.InnoDB行格式 行格式 紧凑的存储特性 增强的可变长度列存储 大型索引键前缀支持 压缩支持 支持的表空间类型 REDUNDANT N N N N system, file-per-table, ...
- 使用Vue3+elementPlus的Tree组件实现一个拖拽文件夹管理
目录 1.前言 2.分析 3. 实现 4.踩坑 4.1.拖拽辅助线的坑 4.2.数据的坑 4.3.限制拖拽 4.4.样式调整 1.前言 最近在做一个文件夹管理的功能,要实现一个树状的文件夹面板.里面包 ...
- 聊聊基于Alink库的推荐系统
概述 Alink提供了一系列与推荐相关的组件,从组件使用得角度来看,需要重点关注如下三个方面: 算法选择 推荐领域有很多算法,常用的有基于物品/用户的协同过滤.ALS.FM算法等.对于不同的数据场景, ...
- Python面向对象——反射(hasattr、getattr、setattr、delattr)、内置方法(__str__和__del__)、元类(介绍,创建类的流程,exec,自定义元类)、属性查找
文章目录 反射 内置方法 __str__方法 __del__函数 元类 元类介绍 class关键字创建类的流程分析 补充:exec的用法 自定义元类控制类StanfordTeacher的创建 自定义元 ...