Golang入门笔记(7)—— 函数 func

news2024/11/15 15:35:52

       函数是什么? 函数:为完成某一功能的程序的语句指令的集合。

   

     感觉重头戏逐渐到来了,让我们好好的,认真对待它吧!

 

        为什么要使用函数? 为了提高代码的复用,减少代码的冗余,提高代码维护性——避免每次都编码一段类似代码。

        基本语法:

func functionName(形参列表...)(返回值的类型列表){
    执行语句...
    return + 返回值列表
}

         其中,如果返回值类型是一个,可省略第二个小括弧,代码如下:

package main

import "fmt"

func main() {
	sum := calculate(10, 20) //实参。
	fmt.Println(sum)
}

func calculate(num1 int, num2 int) int { //形参
	sum := 0
	sum += num1
	sum += num2
	return sum
}

        注意事项:       

  •          函数名:

1.遵循标识符命名规范——驼峰命名法,要能见名知意。

2.首字符不能是数字。

3.如果首字母大写该函数可以被本包文件和其他包文件使用;如果首字母小写只能被本包文件使用,其他包不能使用。

4. Go语言中,函数不支持重载。所以同一block中,函数名不可重复声明,否则会 报 redecleared in this block 的错误。

  •         形参列表:

1. 用于接收外部传入的参数,其参数的个数,可以0个,也可以是n个。

2.支持可变参数,即函数参数的数量可根据实际情况弹性伸缩 。(ps 后面等熟悉了函数后,末尾会专门介绍)

  •         返回值列表:

返回值类型列表:

        1.可以返回0个数据类型,可以返回n个数据类型。

返回0个数据类型

func main() {
	calculate(10, 20)
}

//函数定义中无返回值类型列表
func calculate(num1 int, num2 int)  {
	sum := 0
	sum += num1
	sum += num2
	fmt.Println(sum)
}

返回n个数据类型

package main

func main() {
    //需要2个变量接受此函数返回的多个类型的数据
	r1, r2 := calculate(10, 20)
	println(r1, r2)
}

//返回多个数据类型的函数
func calculate(num1 int, num2 int) (int, int) {
	sum := 0
	sum += num1
	sum += num2

	var result int = num1 - num2
	return sum, result
}

        2. 对于不关注的返回,可以使用_忽略。比如:

//可以用 下划线 ,忽略不关注的返回值。
	r1, _ := calculate(10, 20)
	println(r1)

函数执行内存分析:

        先看一段代码:思考执行结果为什么会这样?

package main

import "fmt"

func main() {
	num1 := 10
	num2 := 20
	exchange(num1, num2)
	fmt.Printf("num1 = %v , num2 = %v", num1, num2) //num1 = 10,num2 = 20
}

func exchange(num1 int, num2 int) {
	var t int
	t = num1
	num1 = num2
	num2 = t
}

        知识预热:

        栈区:用来存储程序执行过程中函数内部定义的信息和局部变量值。 最内层函数后进先出,最内层函数先执行后,释放内存,向上层传递结果。 函数return返回值将函数执行的结果保存下来,返回给调用者。

        上面这个函数,在内存中的函数执行过程,如下图所示:

当exchange执行完毕之后,出栈 销毁函数栈帧(栈空间)——上面exchage栈空间就会出栈而消失

                   以上函数的内存活动的主要发生在逻辑栈上,根据如上图的内存分析就可得出问题所在。

可变参数案例:

        相信在这里,大家已经大致了解了函数了,这里 详细看一下 可变参数的案例。

package main

func main() {
	res := calculate("*", 1, 2, 3, 4)
	println(res)
}

func calculate(op string, num ...int) int {
	res := 1
	if "*" == op {
		for i := 0; i < len(num); i++ {
			res *= num[i]
		}
	}
	return res
}

       注意:可变参数,要是必须是最后一个参数,这是一个通用的语言语法规范,js-ecmascript6版本 和 java 也都是如此。

  •         函数的参数的传递方式:

        基本数据类型和数组默认都是值传递,即进行值得拷贝,在函数内修改,不会影响到原来的值。

package main

import "fmt"

func main() {
	num := 1
	changeValue(num)
	println(num)
}

func changeValue(num int) {
	num = 1000
	fmt.Println(" changeValuetest num  --> ", num)
}

       此种情况为什么会出现这样的结果,大概的原理和上面的内存分析模型几乎差不多的。       

         对于以值传递方式的数据类型,如果希望在函数内的变量能修改函数外的变量,可以传入变量的地址&,函数内以指针的方式操作变量。从效果上看类似 引用传递。

package main

import "fmt"

func main() {
	num := 1
	println("num地址", &num)
	changeValue(&num) //调用函数的时候,传入num的地址。
	println(num)
}

func changeValue(num *int) { // 定义了一个int类型的指针
	//用*访问到这个地址的内存。
	*num = 1000
	fmt.Println(" changeValuetest num  --> ", num)
}

以上代码的内存分析图:

传入 *int变量地址 的方式

Go函数也是一种数据类型
        这点和javascript一样,可以赋值给一个变量,则该变量就是一个函数类型的变量,通过该变量可以调用该函数。正式由于函数是一个数据类型的特性,在Go的世界中,函数可以作为形参传递并且调用。这不禁让我想到Javascript 的cb()函数的使用,以及 java 通过抽象一个接口,做一个匿名内部类等方式有得一拼。

package main

import "fmt"

func main() {

	a := say
	fmt.Printf("a 得类型是 %T,say 函数得类型是 %T \n", a, say)

	a("your")
	say("my")
}

func say(whose string) {
	println("this is " + whose + "callback, just test this feature. ")
}

        根据这种特性,编写回调函数。

package main

func main() {

	a := calculate
	var res int = test(a, 1, 2, 3, 4, 5)
	println(res)
}

func calculate(op string, num ...int) int {
	res := 1
	if "*" == op {
		for i := 0; i < len(num); i++ {
			res *= num[i]
		}
	}
	return res
}

func test(cb func(string, ...int) int, nums ...int) int {
	return cb("*", nums...) // 根据javascript 的 rest 的语法,瞎试的竟然也成了。
}

        编写以上代码的心得体会:

* func 函数当参数传递的时候,细节点,要传入定义好的参数类型和返回值类型。 

* 当遇到可变参数的时候,如这里的 num...  , 可变参数的代表变量要和三个点 在一起打包传递,这样来声明这个是一组可变的参数值。

自定义数据类型(给数据类型别名):

package main

import "fmt"

func main() {
	//自定义数据类型,给类型起了别名。
	type myInt int
	var num1 myInt = 30
	fmt.Println("num1", num1)
	var a int = 20
	//a = num1 // cannot use num1 (variable of type myInt) as type int in assignment
	a = int(num1) // 别名通过 int() 进行强转为原来的类型。
	println(a)
}

自定义函数类型

// 优化前
func test(cb func(string, ...int) int, nums ...int) int {
	return cb("*", nums...) // 根据javascript 的 rest 的语法,瞎试的竟然也成了。
}



//优化后,使用 自定义的函数类型,使得代码更加简洁
type operateFunction func(string, ...int) int

func test(cb operateFunction, nums ...int) int {
	return cb("*", nums...) // 根据javascript 的 rest 的语法,瞎试的竟然也成了。
}

支持函数返回值的命名操作:

package main

func main() {

}

// 返回值的列表顺序必须要和返回值的类型,一一对于,不可弄乱。
func test01(num1 int, num2 int) (int, int) {
	sum := num1 + num2
	sub := num1 - num2
	return sum, sub
}

// 通过返回列表声明的变量 字符 ,可以进行映射。可以不用管顺序,减少编码错误。
func test02(num1 int, num2 int) (sub int, sum int) {
	sum = num1 + num2
	sub = num1 - num2
	return
}

        细节好多,多多练习。

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

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

相关文章

前端框架 React 学习总结

目录 一、React在HTML里的运用 二、React框架的常用操作 1、JSX基础语法规则 2、state数据的使用 3、生命周期 4、数据的双向绑定与Ref 5、PropTypes验证规则 6、React里的插槽 7、错误边界 8、直接操作refs元素 9、高阶组件的运用案例 10、性能优化 11、Hook生命…

Linux中安装mysql8

一、下载MySQL到 /usr/local/src 1、打开官网下载界面 MySQL :: Download MySQL Community Server (Archived Versions) 2、选择某个版本的下载地址 以https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.30-linux-glibc2.12-x86_64.tar.xz这个地址作为例子 …

Kubernetes 系统化学习之 持久存储篇(五)

1. ConfigMap ConfigMap 是一种 API 对象&#xff0c;用来将非机密性的数据保存到键值对中。使用时&#xff0c;Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。ConfigMap 的主要作用就是为了让镜像和配置文件解耦&#xff0c;以便实现镜像的可移植性和可复用性…

day07 Elasticsearch搜索引擎3

day07 Elasticsearch搜索引擎3 1、数据聚合 聚合&#xff08;aggregations&#xff09;可以让我们极其方便的实现对文档数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f;这些手机的平均价格、最高价格、最低价格&#xff1f;这些手机每月的销售…

java设计模式之观察者模式

一&#xff1a;观察者模式 1.什么是观察者模式? 观察者模式是一种行为设计模式&#xff0c; 允许你定义一种订阅机制&#xff0c; 可在对象事件发生时通知多个 “观察” 该对象的其他对象。 观察者模式的基本介绍 又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09…

从阿里云容器攻防矩阵API安全生命周期,看如何构建金融安全云原生平台

【编者按】云原生技术正在助力银行通过差异化业务进行创新&#xff0c;却也带来了由于研发/运维人员对新架构不熟悉所导致的基础设施风险、业务风险及数据暴露风险。如何在飞速更迭的技术环境下保持业务持续发展&#xff0c;同时保证业务整体的安全性&#xff0c;满足不断增强的…

设计模式-装饰器模式

装饰器模式也称为包装模式是指在不改变原有对象的基础上&#xff0c;将功能附加到对象上&#xff0c;提供比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式 装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态的扩展类的功能 装饰器模式通用UML类图 主要角…

培训学校管理系统之家校管理

近年来&#xff0c;伴随着信息技术的进步。除了不少学校开展了数字化校园的建设&#xff0c;一些培训机构也在使用数字化系统进行管理。同时&#xff0c;由于招生数量的不断增长&#xff0c;如何解决学生、教师、家长三者之间的联系沟通问题&#xff0c;促进教学管理任务的有效…

排序(详解)

排序排序的概念常见的排序算法直接插入排序希尔排序&#xff08;缩小增量排序&#xff09;选择排序堆排序冒泡排序快排&#xff08;递归&#xff09;霍尔版本挖坑法前后指针法快排&#xff08;非递归&#xff09;归并排序&#xff08;递归&#xff09;归并排序&#xff08;非递…

区块链动态化监管方案

前言 监控运维模块是区块链BaaS的核心模块之一&#xff0c;我们针对联盟链、主机和系统等多个监控对象提供丰富的监控指标。通过BaaS提供的综合监控大屏&#xff0c;用户可直观洞悉区块链业务全局&#xff0c;实现7*24小时监控全覆盖。 但随着BaaS业务的扩展&#xff0c;对监…

jsp教师教学信息管理系统Myeclipse开发sqlserver数据库web结构java编程计算机网页项目

一、源码特点 JSP 教师教学信息管理系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库文&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为sqlserver2008…

微服务拆分总结(一)

微服务要解决的问题&#xff1a; 1、可以快速迭代&#xff1b; 2、解决三高问题&#xff08;高并发&#xff0c;高可用&#xff0c;高性能&#xff09; 什么时候拆分微服务&#xff0c;拆分的时机是什么&#xff1f; 提交频繁代码冲突&#xff1b; 模块之间耦合严重&#…

RocketMQ 重试机制详解及最佳实践

作者&#xff1a;斜阳 引言 本文主要介绍在使用 RocketMQ 时为什么需要重试与兜底机制&#xff0c;生产者与消费者触发重试的条件和具体行为&#xff0c;如何在 RocketMQ 中合理使用重试机制&#xff0c;帮助构建弹性&#xff0c;高可用系统的最佳实践。 RocketMQ 的重试机制…

[附源码]java毕业设计静谧空间自习室预订系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

服务器部署Vue2脚手架的PIXI游戏项目-知识点注意

文章目录安装PIXI框架方式一&#xff08;安装&#xff09;方式二&#xff08;引入&#xff09;javaScript代码位置initPixi方法组件挂载完毕后调用注意文件导入使用import一个个导入并命名使用setTimeout()方法使用一般方法调用表达式使用安装PIXI框架 方式一&#xff08;安装…

高通量筛选检测方法-分子篇

分子水平的筛选更多的是检测酶/受体功能的改变或探针/蛋白质结合的抑制&#xff0c;或是检测蛋白质-配体结合的结构、动力学和亲和度。 下面将介绍了荧光偏振、荧光共振能量转移、酶联免疫吸附、表面等离子共振和核磁共振技术几种方法。 ■ 荧光偏振 荧光偏振是一项在高通量筛…

2-STM32GPIO输入之按键

文章目录1-硬件设计1.1 按键消斗1.1.1 RS触发器1.1.2 电容滤波2 按键电路设计2.1 软件消斗2.2 硬件消斗2.3 检测原理2-软件设计2.1 软件消斗2.1.1原理2.1.2 编程要点2.1.3 步骤2.2 代码编写2.2.1 主程序2.2.2 按键初始化2.2.2 按键扫描本章讲述GPIO输入的应用&#xff0c;使用独…

第03章_用户与权限管理

第03章_用户与权限管理1 用户管理1.1 登录MySQL服务器1.2 创建用户1.3 修改用户1.4 删除用户1.5 设置当前用户密码1.6 修改其它用户密码1.7 MySQL8密码管理(了解)2. 权限管理2.1 权限列表2.2 授予权限的原则2.3 授予权限2.4 查看权限2.5 收回权限3. 权限表3.1 user表3.2 db表3.…

【springboot】18、内置 Tomcat 配置和切换

文章目录基本介绍Tomcat配置切换其他Web服务总结基本介绍 SpringBoot 支持的 webServer有: Tomcat, Jetty, or Undertow&#xff0c;我们使用spring-boot-starter-web进行web开发时&#xff0c;默认使用的就是Tomcat&#xff0c;下面来说明一下tomcat的配置以及切换其他的Web服…

小啊呜产品读书笔记001:《邱岳的产品手记-05》第9讲 产品案例分析:Hopper的“人工智能” 第10讲 产品被抄袭了怎么办?

小啊呜产品读书笔记001&#xff1a;《邱岳的产品手记-05》第9讲 产品案例分析&#xff1a;Hopper的“人工智能” & 第10讲 产品被抄袭了怎么办&#xff1f;一、今日阅读计划二、泛读&知识摘录1、09 讲 产品案例分析&#xff1a;Hopper的“人工智能”2、10 讲 产品被抄袭…