【GO 编程语言】 函数

news2024/10/6 14:25:49

函数


文章目录

  • 函数
  • 一、什么是函数
    • 1.函数的声明
  • 二、函数的声明和调用
  • 三、形参和实参
  • 四、可变参数
  • 五、值传递和引用传递
  • 六、函数中变量的作用域
  • 七、defer
  • 八、函数的本质探究
  • 九、匿名函数
  • 十、回调函数
  • 十一、闭包


在这里插入图片描述


一、什么是函数

  • 函数是基本的代码块,用于执行一个任务。
  • Go 语言最少有个 main( ) 函数。
  • 可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
  • 函数声明告诉了编译器函数的名称,返回类型,和参数。

1.函数的声明

Go 语言函数定义格式如下:

func functionName( [parameter list] ) [returnType] {
		函数体
}
package main

import "fmt"

/*
	-- 函数是基本的代码块,用于执行一个任务
	-- Go 语言最少有个 main() 函数
	-- 可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务
	-- 函数声明告诉了编译器函数的名称,返回类型和参数
*/

func main() {

	fmt.Println(add(3, 4))

}

// func 函数名 (参数,参数....) 函数调用后的返回值 {
//  函数体 : 执行一段代码
//  return  返回结果
//}

func add(a, b int) int {
	c := a + b
	return c
}

输出
在这里插入图片描述

二、函数的声明和调用

  • 无参数无返回值函数
  • 有一个参数的函数
  • 有两个参数的函数
  • 有一个返回值的函数
  • 有多个返回值的函数
package main

import "fmt"

func main() {

	c := add(3, 4)
	fmt.Println(c)
	onePrint("guan")
	x, y := swap("guan", "hello")
	fmt.Println(x, y)
}

// - 无参数无返回值函数
func Println() {
	fmt.Println("printinfo")
}

// - 有一个参数的函数
func onePrint(name string) {
	fmt.Println("name")
}

// - 有两个参数的函数
// - 有一个返回值的函数
func add(a, b int) int {
	c := a + b
	return c
}

// - 有多个返回值的函数
func swap(x, y string) (string, string) {
	return y, x
}

输出
在这里插入图片描述

三、形参和实参

形式参数:定义函数时,用来接收外埠传入数据的参数,就是形式参数

实际参数:调用函数时,传给形参的实际数据叫做实际参数

package main

func main() {
	maxNum := max(6, 8)
	println(maxNum)

}

// - max 两个数字比大小
// 形式参数:定义函数时,用来接收外埠传入数据的参数,就是形式参数
// 实际参数:调用函数时,传给形参的实际数据叫做实际参数
func max(num1, num2 int) int {
	var result int
	if num1 > num2 {
		result = num1
	} else {
		result = num2
	}
	// 一个函数定义上有返回值,那么函数中必须使用return语句
	// 返回值
	// 调用处需要使用变量接收结果
	return result
}

四、可变参数

概念:一个函数的参数类型确定,但个数不确定,就可以使用可变参数。

func myfunc(arg ... int) {}
// arg ... int 告诉go这个函数接收不定数量的参数,类型全部是int
package main

import "fmt"

func main() {
	getSum(1, 2, 3, 4, 5, 6, 7, 8)
}

// ... 可变参数
func getSum(nums ...int) {
	sum := 0
	// x.len(),获取元素长度
	for i := 0; i < len(nums); i++ {
		// x[i] 通过下标取出数据
		sum += nums[i]
	}
	fmt.Println("总和:", sum)
}

输出
在这里插入图片描述

五、值传递和引用传递

按照数据的存储特点来分:

  • 值类型的数据:操作的是数据木身、int、string、bool、 float64、array…
  • 引川类型的数据:操作的是数据的地址 slice,map, chan…

值传递

package main

import "fmt"

func main() {
	// 定义一个数组
	arr1 := [4]int{1, 2, 3, 4}
	fmt.Println("arr1默认数据", arr1)
	update(arr1)
	fmt.Println("arr1 调用函数后数据", arr1)

	// arr2 的数据是 从arri 复制兴的,所以是不可的空间
	// 修改 arr2 并不会影响 arr 1
	// 值传递:传递的是数据的副本,修改数据,对于原始约数据没有影响
	// 值类型的数据,默认都是值传递:基础炎型、array、struct
}

func update(arr2 [4]int) {
	fmt.Println("arr2 接以数据", arr2)
	arr2[0] = 10
	fmt.Println("arr2 修改后数据", arr2)
}

输出
在这里插入图片描述
注意事项:

  • 如果一个函数的参数是可变参数,同时还有其他的参数,可变参数要放在列表的最后。
  • 一个函数的参数列表中最多只能有一个可变参数。

六、函数中变量的作用域

  • 作用域:变量可以使用的范围
  • 局部变量:函数内部定义的变量,叫做局部变量
package main

import "fmt"

func main() {
	// 函数体内的局部变量
	y := 66
	if z := 1; z <= 10 {
		// 语句内的局部变量
		y := 88
		fmt.Println(y) // 局部变量,就近原则
		fmt.Println(z)
	}
	fmt.Println(y)
	//fmt.Println(z) // # command-line-arguments
	// .\hello.go:15:14: undefined: z
}

func gun01() {
	// x 为局部变量
	x := 1
	println(x)
}

func gun02() {
	// fmt.Println(a) //不能在使用在其他函数定义的变量
}

  • 全部变量:函数外部定义的变量,叫做全局变量
package main

import "fmt"

// 全局变量
var num int = 99

func main() {
	//num := 1
	fmt.Println(num)
	gun01()
	gun02()
}

func gun01() {
	//num := 2
	println(num)
}

func gun02() {
	//num := 3
	fmt.Println(num)
}

输出
在这里插入图片描述

在这里插入图片描述

七、defer

defer 语义:推迟、延迟

在Go语言中,使用 defer 关键字来延迟一个函数或者方法的执行。

package main

import "fmt"

func main() {
	num := 1
	fmt.Println(num)
	defer gun01() // 会被延迟到最后执行
	gun02()
}

func gun01() {
	num := 2
	println(num)
}

func gun02() {
	num := 3
	fmt.Println(num)
}

输出
在这里插入图片描述

defer函数或者方法:个函数或方法的执行被延迟了

  • 可以在函数中添加多个defer语句,当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回,特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题
  • 如果有很多调用 defer,那么 defer 是采用 后讲先出(栈)模式。
package main

import "fmt"

func main() {
	num := 1
	num01 := 6
	fmt.Println(num)
	defer gun01() // 会被延迟到最后执行
	defer gun02()
	defer fmt.Println(num01)
}

func gun01() {
	num := 2
	println(num)
}

func gun02() {
	num := 3
	fmt.Println(num)
}

输出
在这里插入图片描述

import "fmt"

func main() {
	num := 1
	a := 6
	fmt.Println(num)
	defer gun01(a) // 在执行a++之前,参数就已经传递进去了,在最后执行
	a++
	fmt.Println(a)

}

func gun01(x int) {

	println(x)
}

输出
在这里插入图片描述

八、函数的本质探究

package main

import "fmt"

// func() 本身就是一个数据类型
func main() {
	// f1 如果不加括号,函数也是一个变量
	// f1() 如果加了括号,那就成了函数的调用
	fmt.Print("%T\n", f1)

	// f1 看着对应函数名对应函数体的地址 0xbbfd60
	// f1() 带括号就是将函数直接调用

	// 直接定义一个函数类型的变量
	fmt.Println()
	var x func(int, int)
	fmt.Println(x)

	// 将格式相同的f1给x进行函数赋值
	x = f1
	fmt.Println(x) // 和f1地址相同

	f1(1, 2)
	x(10, 20) //x也是函数类型的,可以直接调用
}

func f1(a, b int) {
	fmt.Printf("a:%d,b:%d\n", a, b)
}

在这里插入图片描述
函数在 Go 语言中是复合类型,可以看做是一种特殊的变量。
函数名( ): 调用返回结果
函数名:指向函数体的内存地址,一种特殊类型的指针变量

九、匿名函数

package main

import "fmt"

// func() 本身就是一个数据类型
func main() {
	f1()
	f2 := f1 //函数本身也是一个变量
	f2()

	// 匿名函数
	f3 := func() {
		fmt.Println("f3函数")
	}
	f3()

	func() {
		fmt.Println("f4函数")
	}() // 匿名函数本身可以调用自己

	func(a, b int) {
		fmt.Println(a, b)
		fmt.Println("f5函数")
	}(3, 4) // 匿名函数本身可以调用自己

	x := func(a, b int) int {
		fmt.Println("f6函数")
		return a + b

	}(3, 4) // 匿名函数本身可以调用自己
	fmt.Println(x)
}

func f1() {
	fmt.Println("f1函数")
}

Go 语言是支持函数式编程:
1、将匿名函数作为另一个函数的参数,回调函数
2、将匿名函数作为另外一个函数的返回值,可以形成闭包结构

十、回调函数

根据Go语言的数据类型的特点,可以将一个函数作为另外一个函数的参数
fun1()、fun2() 将 fun1 函数作为 fun2 这个函数的参数

fun2函数:叫做高阶函数,接收一个函数作为参数的函数

fun1函数:叫做回调函数,作为另外一个函数的参数

package main

import "fmt"

func main() {
	r1 := Sum(1, 1)
	fmt.Println(r1)

	r2 := oper(5, 5, Sum)
	fmt.Println(r2)

	r3 := oper(10, 5, Sub)
	fmt.Println(r3)

	r4 := oper(10, 5, func(a int, b int) int {
		if b == 0 {
			fmt.Println("除数不能为0")
			return 0
		}
		return a / b
	})
	fmt.Println(r4)
}

// 高阶函数,可以接收一个函数作为参数
func oper(a, b int, f func(int, int) int) int {
	r := f(a, b)
	return r

}

func Sum(a, b int) int {
	return a + b
}

func Sub(a, b int) int {
	return a - b
}

输出
在这里插入图片描述

十一、闭包

  • 一个外层函数中,有人层函数,该人层函数中,会操作外层函数的局部变量廿月该外层函数约返回传就是这个人层函数。这个内层羽数和外层尿数的灵部变量,统称为闭包结构

  • 局部变量约牛命周期就会发生改变,正常的局部变量会随着函数的调月而创建,随着函数的结束而销毁作是闭勺结构中约外票列数的局部变量并不会随着外层函数的计束而销毁,因为内票函数证什继续使用



package main

import "fmt"

func main() {
	r1 := increment()
	fmt.Println(r1)

	v1 := r1()
	fmt.Println(v1)

	v2 := r1()
	fmt.Println(v2)
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())

	r2 := increment()
	v3 := r2()
	fmt.Println(v3)
	fmt.Println(r1())
	fmt.Println(r2())
}

func increment() func() int {
	// 局部变量i
	i := 0
	// 定义一个匿名函数,给变量自增并返回
	f := func() int {
		i++
		return i
	}
	return f
}




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/509963.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【手撕代码系列】JS手写实现apply方法

公众号&#xff1a;Code程序人生&#xff0c;分享前端所见所闻 在JavaScript中&#xff0c;apply()是Function对象的一个方法&#xff0c;它允许我们以指定的this值和参数列表调用函数。这个方法通常被用来在函数调用时动态地传递参数&#xff0c;或者在调用函数时绑定this值。…

chatgpt软件批量写作软件-文章改编软件

文章改编软件 文章改编软件是一种能够将原有的文本进行复制粘贴后&#xff0c;通过一定算法进行改写和改编的工具。其主要应用领域在于将一些内容复制到网站或博客等平台上时&#xff0c;避免因为重复内容而被识别为“抄袭”&#xff0c;从而提高文章的独特性和可读性。 然而…

TweenMax 源码阅读

GSAP 之 TweenMax 源码阅读&#xff08;一&#xff09; 一、背景 GreenSock &#xff08;绿袜子&#xff09; GreenSock 是一家做 专业级 JavaScript 动画的公司&#xff0c;主要产品就是其下的 GSAP (GreenSock Animation Platform)&#xff0c;配合着 GSPA 开发了很多专业的…

前端架构师-week5-egg.js+云Mongodb快速入门

目录 下载项目模版功能实现流程分析egg.js简介 egg.js 官网 初始化 云 mongodb 云 mongodb 开通 本地 mongodb 安装 mongodb 使用方法 通过 egg.js 框架添加新的API 云 mongodb 开通 本地 mongodb 调试技巧讲解 egg.js 接入 mongodb 方法 云 mongodb 如何连接公网…

mysql深分页

第一种&#xff1a;主键自增id情况&#xff1a; 未改&#xff1a; select * from wx_product_category_info where category_name_cn#{categoryNameCn} and category_type#{categoryType} order by id asclimit #{pageNum}, #{pageSize};在普通的limit条件下&#xff0c;如果…

如何通过appuploader把ipa文件上传到App Store教程步骤

​ iOS APP上架App Store其中一个步骤就是要把ipa文件上传到App Store&#xff01;​ 下面进行步骤介绍&#xff01;​ 利用Appuploader这个软件&#xff0c;可以在Windows、Linux或Mac系统中申请ios和上传IPA到App Store Connect。​ 非常的方便&#xff0c;没有Mac也可以…

回炉重造十三----Docker的运用

1、Docker和虚拟机的区别 两者的区别 虚拟化环境下每个 VM 是一台完整的计算机&#xff0c;在虚拟化硬件之上运行所有组件&#xff0c;包括其自己的操作系统。 容器之间可以共享操作系统,比起 VM 被认为是更轻量级.且与 VM 类似&#xff0c;每个容器都具有自己的文件系统、CPU…

42电机插座接线可以用PH2.0冷压端子

文章目录 42电机插座接线可以用PH2.0冷压端子概述笔记备注END 42电机插座接线可以用PH2.0冷压端子 概述 设备上的42电机在我不断调整电机安装位置时, 接线从插孔中折断了. 问厂家, 他们的线也是定制的. 另外, 他是销售, 不清楚具体插座的型号和插座要用的冷压端子是哪种. 因为…

Java 关键字之:package与import

一、package 关键字 为了更好的实现项目中类的管理&#xff0c;提供包的概念使用package声明类或者接口所属的包&#xff0c;声明在源文件的首行包&#xff0c;属于标识符&#xff0c;遵循标识符的命名规则、规范(xxxyyyzzz)、"见名知意"每“.”一次&#xff0c;就代…

windows 下安装Docker (WSL2)

测试环境&#xff1a; VMware Workstation 17 WinServer2022 docker 4.19 python3.8 第一步&#xff1a;环境准备&#xff1a; 1.开启虚拟化 2. 开启WSL、容器功能 重启服务器 第二步&#xff1a; 安装docker 桌面版&#xff1a;Get Docker | Docker Documentation 此时启动会…

Django框架之错误视图和HTTP方法装饰器

本篇主要记录如何定义视图&#xff0c;错误视图有哪些并如何实现自定义&#xff0c; HTTP方法装饰器定义及实现&#xff0c;还有csrf中间件设置位置及关闭。 定义视图 一般在views.py文件下定义 视图参数&#xff1a; 错误视图 400视图 当出现SuspiciousOperation异常并且代…

Linux Kernel内核整体架构(图文详解)

1&#xff0c;前言 本文是“Linux内核分析”系列文章的第一篇&#xff0c;会以内核的核心功能为出发点&#xff0c;描述Linux内核的整体架构&#xff0c;以及架构之下主要的软件子系统。之后&#xff0c;会介绍Linux内核源文件的目录结构&#xff0c;并和各个软件子系统对应。…

WPF 从0开始写笔记,全属性功能深度剖析 20230510

文章目录 FontFamilyFontWeightResizeModeAllowsTransparencyMarginCornerRadiusBorder.effectBlurRadiusdirectionVerticalAlignmentTargetTypeControlTemplateDataTemplate 和ControlTemplate的区别StrokePath控件Border FontFamily 在WPF中&#xff0c;FontFamily属性用于指…

5月第1周榜单丨飞瓜数据B站UP主排行榜(哔哩哔哩平台)发布!

飞瓜轻数发布2023年5月1日-5月7日飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数三个维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营能力强的B站…

【C++】类型转换-static_cast、reinterpret_cast、const_cast、dynamic_cast

文章目录 1. C语言中的类型转换2. 为什么C需要四种类型转换3. C强制类型转换static_castreinterpret_castconst_castdynamic_cast 4.explicit5.RTTI6.考点 1. C语言中的类型转换 在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与接收返回…

网易云信 RTC 音频问题排查的挑战与实践

背景与挑战 实时通信&#xff08;Real-Time Communication&#xff0c;RTC&#xff09;音频技术是指将音频流实时传输到远程用户的技术&#xff0c;满足线上实时交互的诉求&#xff0c;广泛应用于在线教育、视频会议、直播、泛娱乐社交、金融、医疗、政企等场景。在 RTC PaaS…

组件通信的几种方式

组件通信的几种方式 父组件向子组件传值 在父组件中用自定义组件进行传值&#xff0c;自定义属性写到父组件调用子组件的那个标签中。在子组件中用props进行接收&#xff0c;props写到子组件中与data同级&#xff0c;props是一个数组&#xff0c;内容就是自定义属性的名字。 …

SD nand 与 SD卡的SPI模式驱动

文章目录 SD nand 与 SD卡的SPI模式驱动 1. 概述 2. SPI接口模式与SD接口模式区别 2.1 接口模式区别 2.2 硬件引脚 2.3 注意事项 3. SD接口协议 3.1 命令 3.1.1 命令格式 3.1.2 命令类型 3.2 响应 3.2.1 响应格式 4. SD nand&#xff08;SD卡&#xff09;结构描述…

内网渗透之域环境信息搜集

1.查看是否为域环境 net config workstation下面命令能否执行成功和computer brower服务是否开启有关 net view /domain2.查询域内的用户和组 查询域内的所有用户 net user /domain查询域内的所有用户(需要在域控上敲) dsquery user查询域内的某个用户 net user dbadmin /d…

代码随想录算法训练营day36 | 435. 无重叠区间,763.划分字母区间,56. 合并区间

代码随想录算法训练营day36 | 435. 无重叠区间&#xff0c;763.划分字母区间&#xff0c;56. 合并区间 435. 无重叠区间763.划分字母区间56. 合并区间总结 435. 无重叠区间 教程视频&#xff1a;https://www.bilibili.com/video/BV1A14y1c7E1/?spm_id_from333.788&vd_sou…