当前位置: 首页 > news >正文

8 Go的函数

概述

        在上一节的内容中,我们介绍了Go的指针,包括:使用指针、空指针、指针数组、指向指针的指针等。在本节中,我们将介绍Go的函数。函数允许开发者将相关的代码组织在一起,并将其命名,以便在其他地方进行调用。在Go语言中,函数是一段可重用的代码块,用于执行特定的操作。

函数定义

        函数定义的基本格式如下:

func funcName(parameter1 type, parameter2 type) returnType {  // 函数体  // 可以在这里执行一些操作  // 函数结束时,可返回一个或多个值  return value1, value2, ...  
}

        下面详细介绍上述格式中的各个元素。

        func:关键字,用于声明一个函数。

        funcName:函数的名称,用于标识函数的唯一标识符。

        parameter1, parameter2:函数的参数列表,每个参数由参数名称和参数类型组成。参数是可选的,也就是说,函数可以不包含任何参数。

        type:参数的数据类型,可以是任何有效的Go数据类型,比如:整数、浮点数、字符串等。

        returnType:函数返回值的类型,该参数是可选的。如果函数不返回任何值,则返回类型为void或();如果函数返回一个值,则该值的数据类型将指定为返回类型;如果函数返回多个值,则需要依次给出这些值的数据类型。

        return value1, value2, ...:函数返回语句,用于指定函数返回的值。可以返回单个值,也可以返回多个值。如果没有值需要返回,则可以省略return语句。

        在下面的示例代码中,我们定义了三个函数。第一个函数MyPrint没有返回值,第二个函数Add有一个返回值,第三个函数Process有两个返回值。

package mainimport "fmt"// 没有返回值
func MyPrint(text string) {fmt.Println(text)
}// 一个返回值
func Add(a int, b int) int {return a + b
}// 多个返回值
func Process(data int) (int, string) {if data >= 100 {return 0, "OK"}return -1, "Invalid"
}func main() {MyPrint("Hello CSDN")sum := Add(100, 200)// 输出:300fmt.Println(sum)result, info := Process(188)// 输出:0 OKfmt.Println(result, info)
}

函数声明

        在Go语言中,函数声明和函数定义是两个相关的概念,但它们还是有一些区别的。

        函数定义用于完整地编写函数的代码块,包括:函数名、参数列表、返回类型和函数体。它实现了函数的具体逻辑,函数定义在程序中只应该有一次。

        函数声明用于告诉编译器函数的名称、参数列表和返回类型,以便在其他地方使用该函数。它包括函数名、参数列表和返回类型,但没有函数体。函数声明是告诉编译器:“有一个这样的函数,可以这样调用它”。

        与C/C++语言不同,Go语言是不区分头文件和实现文件的。Go语言中的函数、变量、结构体等可以在同一个文件中定义和实现,也可以在不同的文件中定义和实现。在编写源码时,可以将函数的声明和定义放在同一个文件中,也可以将它们分别放在不同的文件中。

函数调用

        调用函数,可以通过两种方式来传递参数:一种是值传递,另一种是引用传递。值传递是指在调用函数时,将实际参数复制一份传递到函数中。这样,在函数中如果对参数进行修改,将不会影响到实际参数。引用传递是指在调用函数时,将实际参数的地址传递到函数中。这样,在函数中对参数所进行的修改,将影响到实际参数。默认情况下,Go语言使用的是值传递,即在调用过程中不会影响到实际参数。

        在下面的示例代码中,我们声明并定义了两个函数。Process1函数采用值传递的方式,故调用后number不变。Process2函数采用引用传递的方式,故调用后number值会修改为166。

package mainimport "fmt"// 值传递
func Process1(number int) {number += 100
}// 引用传递
func Process2(pNumber *int) {*pNumber += 100
}func main() {number := 66Process1(number);// 输出:66fmt.Println(number)Process2(&number);// 输出:166fmt.Println(number)
}

        在Go语言中,可以使用多个返回值来返回多个结果。这些返回值可以是不同的数据类型,并可一起打包到一个元组中。函数有多个返回值时,我们可以使用占位符来忽略不需要的返回值,占位符使用下划线(_)来表示。

package mainimport "fmt"func Calc(x, y int) (int, int) {return x + y, x * x + y * y
}func main() {// 多个返回值,依次赋值sum, square := Calc(6, 8)// 输出:14 100fmt.Println(sum, square)// 使用占位符,忽略第一个返回值_, square2 := Calc(6, 8)// 输出:100fmt.Println(square2)
}

可变参数函数

        可变参数函数是一种可以接受可变数量的参数的函数,通过使用省略号...来声明可变参数,可以使得函数接受任意数量的相同类型的参数。可变参数函数在调用时,传递给函数的参数会被当作一个切片传递给函数。在函数内部,可以使用切片来访问和操作这些参数。

        在下面的示例代码中,sum函数是一个可变参数函数,它接受一个或多个int类型的参数。在函数定义中,参数名numbers后面的...表示这是一个可变参数。在函数体中,可以使用numbers切片来访问传递给函数的所有参数。通过遍历切片,可以计算所有参数的和并返回结果。在main主函数中,我们调用sum函数并传递多个整数参数。这些整数会被自动打包成一个切片,然后传递给sum函数。

package mainimport "fmt"func sum(numbers ...int) int {total := 0for _, value := range numbers {total += value}return total
}  func main() {// 输出:300fmt.Println(sum(100, 200))// 输出:600fmt.Println(sum(100, 200, 300))
}

匿名函数

        匿名函数,也称为闭包。匿名函数是一个没有声明名称的函数,可以直接在代码中使用。在下面的示例代码中,我们定义了一个匿名函数并将其赋值给变量add。然后,我们调用add函数并将结果赋值给了变量result。最后,我们输出了result的值。

package mainimport "fmt"func main() {// 定义匿名函数add := func(a, b int) int {return a + b}result := add(66, 88)// 输出:154fmt.Println(result)
}

        匿名函数可以访问其外部的变量,这就是所谓的闭包特性。在下面的示例代码中,我们定义了一个名为origin的变量,并将其初始化为1000。然后,我们定义了一个匿名函数,并将其赋值给add变量。在匿名函数中,我们访问了外部定义的origin变量。最后,我们通过add变量调用了匿名函数。

package mainimport "fmt"func main() {origin := 1000// 匿名函数可以访问外部变量add := func(a, b int) int {return a + b + origin}result := add(66, 88)// 输出:1154fmt.Println(result)
}

递归函数

        在Go语言中,可以使用递归函数,也就是一个函数在自身内部调用自身。递归函数通常用于解决需要重复执行相同操作的问题,比如:计算阶乘、斐波那契数列等。需要注意的是,递归函数必须有一个终止条件。否则,会无限递归下去,导致栈溢出甚至程序崩溃。

        在下面的示例代码中,我们定义了一个名为factorial的递归函数。它接受一个整数n作为参数,并返回n的阶乘。如果n等于0,则返回1;否则,返回n乘以factorial(n-1)的结果。在主函数中,我们调用factorial函数并将结果打印出来。

package mainimport "fmt"func factorial(n int) int {if n == 0 {return 1}return n * factorial(n - 1)
}  func main() {num := 5result := factorial(num)// 输出:5! = 120fmt.Printf("%d! = %d\n", num, result)  
}

高阶函数

        高阶函数是Go语言中函数的一重要特性,它使得函数可以作为参数传递给其他函数,也可以作为函数的返回值。高阶函数在Go语言中非常有用,可以实现更灵活和可复用的代码。通过将函数作为参数传递给其他函数,我们可以实现函数的组合和管道化,从而简化代码并提高可读性。

        在下面的示例代码中,我们定义了一个名为ApplyFunc的高阶函数。它接受一个函数作为参数f,并使用给定的值x、y调用该函数。然后,我们定义了两个简单的函数Add和Sub,用于对传入的两个参数进行加法和减法。最后,我们将Add函数和Sub函数作为参数传递给ApplyFunc函数,并将函数的执行结果赋值给变量result。

package mainimport "fmt"// 定义一个高阶函数,接受一个函数作为参数
func ApplyFunc(f func(int, int) int, x int, y int) int {return f(x, y)
}func Add(x int, y int) int {return x + y
}func Sub(x int, y int) int {return x - y
}func main() {result := ApplyFunc(Add, 99, 66)// 输出结果:165fmt.Println(result)result = ApplyFunc(Sub, 99, 66)// 输出结果:33fmt.Println(result)
}

相关文章:

8 Go的函数

概述 在上一节的内容中,我们介绍了Go的指针,包括:使用指针、空指针、指针数组、指向指针的指针等。在本节中,我们将介绍Go的函数。函数允许开发者将相关的代码组织在一起,并将其命名,以便在其他地方进行调用…...

算法笔记-第九章-二叉树的遍历(待整理)

算法笔记-第九章-二叉树的遍历 二叉树的先序遍历二叉树的中序遍历二叉树的先序遍历 //二叉树的先序遍历 #include <cstdio> #include <vector> using namespace std;const int MAXN = 50;struct Node //用结构体表示左子树和右子树的数据 {int l, r; } nodes[MAXN]…...

C语言从入门到精通之【字符串】

C语言没有专门用于储存字符串的变量类型&#xff0c;字符串都被储存在char类型的数组中。数组由连续的存储单元组成&#xff0c;字符串中的字符被储存在相邻的存储单元中&#xff0c;每个单元储存一个字符&#xff0c;每个字符占1个字节。 数组末尾位置的字符\0。这是空字符&am…...

超详细!必看!!STM32--时钟树原理

一、什么是时钟&#xff1f; 时钟是单片机的脉搏&#xff0c;是系统工作的同步节拍。单片机上至CPU&#xff0c;下至总线外设&#xff0c;它们工作时序的配合&#xff0c;都需要一个同步的时钟信号来统一指挥。时钟信号是周期性的脉冲信号。 二、什么是时钟树&#xff1f; S…...

用 Golang 采集 Nginx 接口流量大小

简介 在开发和运维中&#xff0c;我们经常需要监控和分析服务器的接口流量大小&#xff0c;特别是对于部署了 Nginx 的服务器。本文将介绍如何使用 Golang 采集 Nginx 接口流量大小&#xff0c;并展示如何将这些数据进行实时监控和分析。 步骤一&#xff1a;准备工作 在开始…...

Linux java jar启停脚本(合并版)

#包文件路径及名称(目录按照各自配置) APP_NAME=/opt/whkc/gs/app-java.jar#查询进程,并杀掉当前jar/java程序 pid=`ps -ef|grep app-java.jar | grep -v grep | awk {print $2}` kill...

计算机毕业设计选题推荐-公共浴池微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

sqli-labs关卡13(基于post提交的单引号加括号的报错盲注)通关思路

文章目录 前言一、回顾第十二关知识点二、靶场第十三关通关思路1、判断注入点2、爆显位3、爆数据库名4、爆数据库表5、爆数据库列6、爆数据库关键信息 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。注意靶场是可以练习的平台&#xff0c;…...

SparkAi创作系统ChatGPT网站源码+详细搭建部署教程+AI绘画系统+支持GPT4.0+Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…...

shiro默认session设置永不超时

Shiro默认情况下session是有超时时间的&#xff0c;而不是永不超时。默认的超时时间是30分钟&#xff0c;可以通过修改Shiro的配置文件来更改超时时间。如果想要让session永不超时&#xff0c;可以将超时时间设置为一个很大的值&#xff0c;例如Integer.MAX_VALUE。 以下是修改…...

前端食堂技术周刊第 104 期:Angular v17、GPTs、Vue vapor mode、Svelte Flow、Bundler 的设计取舍

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;金奖乳鸽 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来看下…...

list复制出新的list后修改元素,也更改了旧的list?

例子 addAll() Testpublic void CopyListTest(){Student student Student.builder().id(1).name("张三").age(23).classId(1).build();Student student2 Student.builder().id(2).name("李四").age(22).classId(1).build();List<Student> student…...

Qt绘制各种图形

重载绘图事件&#xff1a; protected:void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;void Widget::paintEvent(QPaintEvent *event) { 进行绘图操作 } 绘图前操作&#xff1a; //基本绘图QPainter painter(this);//创建QPainter对象painter.setRenderHint(QPa…...

NIO 笔记(二)Netty框架专题

【笔记来自&#xff1a;it白马】 Netty框架 前面我们学习了Java为我们提供的NIO框架&#xff0c;提供使用NIO提供的三大组件&#xff0c;我们就可以编写更加高性能的客户端/服务端网络程序了&#xff0c;甚至还可以自行规定一种通信协议进行通信。 NIO框架存在的问题 但是之…...

HTTP——

HTTP 请求报文的构成 如下图: 第一行:HTTP请求的方法,具体是POST方法还是GET方法,或是其它方法;URI就是你的HTTP请求的路径;后面是HTTP协议的版本; 第二行往下连续多行:这些是请求头部分,也就是请求的首部设置的一些信息,相当于对HTTP请求的一些设置; 空格行:在…...

第13章 Java IO流处理(二) 字节流与字符流

目录 内容说明 章节内容 1、I/O与流 2、输入流和输出流 3、字节流与字符流...

【论文阅读】(CTGAN)Modeling Tabular data using Conditional GAN

论文地址&#xff1a;[1907.00503] Modeling Tabular data using Conditional GAN (arxiv.org) 摘要 对表格数据中行的概率分布进行建模并生成真实的合成数据是一项非常重要的任务&#xff0c;有着许多挑战。本文设计了CTGAN&#xff0c;使用条件生成器解决挑战。为了帮助进行公…...

如何进行iOS技术博客的备案?

​ 如何进行iOS技术博客的备案&#xff1f; 标题&#xff1a;iOS技术博客备案流程及要求解析 摘要&#xff1a; 在本篇问答中&#xff0c;我们将为iOS技术博主介绍如何进行备案。如果你的iOS应用只包含简单的页面&#xff0c;并通过蓝牙进行数据采集和传输&#xff0c;那么你…...

RTSP/Onvif安防平台EasyNVR批量禁用/启用通道接口的详细操作步骤

TSINGSEE青犀视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入&#xff0c;并能对接入的视频流进行处理与多端分发&#xff0c;包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。在智慧安防等视频监控场景中&#xff0c;EasyNVR可提供视频实时监控直播、云端…...

2个器件,做1个恒流源

在项目中经常要用到恒流源&#xff0c;查找资料可以使用电压源芯片LM317构造一个电流源芯片。本文将电压源加上一个电阻改为电流源&#xff0c;这种设计思路可以扩展到其他类型的电源芯片上&#xff0c;如开关电源及其他类型的线性电源&#xff0c;关键点在于基准电压VREF的使用…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...