学习函数式编程、可变参数及 defer - GO语言从入门到实战

news2024/11/18 0:32:51

函数是⼀等公⺠、学习函数式编程、可变参数及 defer - GO语言从入门到实战

函数是⼀等公⺠、学习函数式编程、可变参数及 defer

函数是⼀等公⺠

在Go语言中,函数可以分配给一个变量,可以作为函数的参数,也可以作为函数的返回值。这样的行为就可以理解为函数属于一等公民。

与其他主要编程语⾔的差异

  1. 可以有多个返回值:与其他一些编程语言不同,Go语言中的函数可以返回多个值。这使得函数可以更有效地处理和传递多个结果。例如,你可以使用两个变量来接收函数的两个返回值。
package fn_test

import (
	"fmt"
)
func divideAndRemainder(dividend, divisor int) (int, int) {
    quotient := dividend / divisor
    remainder := dividend % divisor
    return quotient, remainder
}

a, b := divideAndRemainder(10, 3)
fmt.Println(a, b) // 输出:3 1

  1. 所有参数都是值传递:在Go语言中,函数参数是通过值传递的。当你将一个变量作为参数传递给函数时,函数会创建该变量的一个副本,而不是直接操作原始变量。这有时会让人产生错觉,认为传递的是引用,但实际上是值传递。但是,对于切片(slice)、映射(map)和通道(channel)这样的引用类型,情况会有所不同。它们在函数间传递时会传递引用,而不是复制整个数据。这意味着如果你在函数内部修改了这些类型的参数,会影响原始变量的值。
package fn_test

import (
	"fmt"
)
func modifySlice(s []int) {
    s[0] = 100
}

nums := []int{1, 2, 3, 4, 5}
modifySlice(nums)
fmt.Println(nums) // 输出:[100 2 3 4 5]
  1. 函数可以作为变量的值:在Go语言中,函数可以作为变量保存和使用。这使得你可以将函数作为参数传递给其他函数,或者将它们赋值给变量。这在实现高阶函数和函数式编程范式时非常有用。
package fn_test

import (
	"fmt"
)
func add(a, b int) int {
    return a + b
}

addition := add // 将函数add赋值给变量addition
fmt.Println(addition(2, 3)) // 输出:5

  1. 函数可以作为参数和返回值:和其他编程语言一样,Go语言的函数可以作为参数传递给其他函数,也可以作为返回值返回。这种能力使得你可以在函数之间传递和返回操作,从而增强代码的模块化和复用性。

这些特性使得Go语言的函数比其他许多编程语言更加灵活和强大。

函数:可变参数及 defer

可变参数

可变参数允许我们在调用函数时传入任意数量的整数。函数的功能是将所有传入的整数相加,然后返回总和。

package main

import "fmt"

func sum(ops ...int) int {
    s := 0
    for _, op := range ops {
        s += op
    }
    return s
}

func main() {
    fmt.Println(sum(1, 2, 3, 4, 5)) // 输出: 15
    fmt.Println(sum(10, 20, 30))    // 输出: 60
}

在上述例子中,sum函数被调用了两次,每次都传入了一些整数。第一次传入的整数是1, 2, 3, 4, 5,总和是15;第二次传入的整数是10, 20, 30,总和是60。

defer 函数

defer语句可以用来释放资源、关闭文件、打印日志等,它具有很高的灵活性,是Go语言中常用的编程技巧之一。使用defer语句需要注意以下几点:

  1. defer语句必须放在函数内部;
  2. 多个defer语句的执行顺序是与其压入栈中的顺序相反的;
  3. defer语句中的变量在执行时会被记录下来,而不是在执行时读取;
  4. defer语句中的函数会在执行时被调用,而不是在压入栈时调用。
package main

import "testing"

func TestDefer(t *testing.T) {
    t.Log("Started")
    defer func() {
        t.Log("Clear resources")
    }()
    // 其他测试代码
}

defer语句位于TestDefer函数的末尾,当这个函数执行结束时,defer语句中的函数将会被执行,打印出"Clear resources"。

下面提供函数应用的代码案例:

package fn_test

import (
	"fmt"
	"math/rand"
	"testing"
	"time"
)
//函数会生成两个随机数,一个在0到9之间,一个在0到19之间。
func returnMultiValues() (int, int) {
	return rand.Intn(10), rand.Intn(20)
}

//函数接受一个函数作为参数,返回一个新的函数。新函数会计算传入函数的运行时间,并打印出来。
func timeSpent(inner func(op int) int) func(op int) int {
	return func(n int) int {
		start := time.Now()
		ret := inner(n)
		fmt.Println("time spent:", time.Since(start).Seconds())
		return ret
	}
}

//函数会让程序暂停1秒,然后返回传入的运算。
func slowFun(op int) int {
	time.Sleep(time.Second * 1)
	return op
}

//首先调用returnMultiValues函数并打印结果,然后创建了一个新的函数tsSF,它内部调用了slowFun并打印其运行时间,最后调用tsSF函数并打印结果。
func TestFn(t *testing.T) {
	a, _ := returnMultiValues()
	t.Log(a)
	tsSF := timeSpent(slowFun)
	t.Log(tsSF(10))
}

//函数接收任意数量的整数参数,并返回它们的和。
func Sum(ops ...int) int {
	ret := 0
	for _, op := range ops {
		ret += op
	}
	return ret
}

//函数调用了Sum函数两次,分别传入4个和5个整数,并打印结果。
func TestVarParam(t *testing.T) {
	t.Log(Sum(1, 2, 3, 4))
	t.Log(Sum(1, 2, 3, 4, 5))
}

//函数打印"Clear resources."。
func Clear() {
	fmt.Println("Clear resources.")
}

//首先打印"Start",然后触发一个panic,最后执行defer Clear(),清除资源。
func TestDefer(t *testing.T) {
	defer Clear()
	fmt.Println("Start")
	panic("err")	//panic是一种用于处理程序错误和异常情况的机制,类似于其他语言的异常
}

学习Go语言主要是多练,多找些代码段写写,不懂可以私聊咨询。
码字不易,如果该文章有用,请多多关注或者赞赏,谢谢!

欢迎关注云尔Websites CSDN博客

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

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

相关文章

Nodejs内置模块process

文章目录 内置模块process写在前面1. arch()2. cwd()3. argv4. memoryUsage()5. exit()6. kill()7. env【最常用】 内置模块process 写在前面 process是Nodejs操作当前进程和控制当前进程的API,并且是挂载到globalThis下面的全局API。 下面是process的一些常用AP…

linux开发板中的数据存储和读取操作

问题:MQTT远程下发的参数存储在本地linux开发板,开发板依据该参数执行相应功能,当开发板重新上电时依然能继续执行该功能 解决方式: 在linux板中写一个标识并存储为文件,依据读取的文件标识执行相应的功能 1)打开文…

【2023】M1/M2 Mac 导入Flac音频到Pr的终极解决方案

介绍 原作者链接:https://github.com/fnordware/AdobeOgg 很早之前就发现了这个插件,超级好用,在windows上完全没有问题,可惜移植到mac就不行了(然后我给作者发了一个Issue,后来就有大佬把m1的编译出来了&…

Ai绘画描述词 关键词大全 真人美女 二次元卡通美女 国漫动漫效果

超好看的二次元动漫美少年 都是用Ai工具直接绘画生成出来的。 还有真人绘画,效果也很逼真 还有更多的场景效果 寂静天空素材 做抖音 短视频 精美的图片素材都是通过Ai绘画的 但是绘画需要关键词去描述场景,Ai才能自动根据场景描述词生成出来图片。 如何…

【Java学习之道】接口与抽象类

引言 现在我们来聊聊接口和抽象类。在Java中,接口和抽象类是实现OOP的重要工具,它们允许我们定义规范和行为,让代码更具灵活性和可扩展性。这一节,我们就来详细探讨一下这两个神奇的功能。 一、接口 接口是一个完全抽象的类&am…

【LeetCode高频SQL50题-基础版】打卡第6天:第31~35题

文章目录 【LeetCode高频SQL50题-基础版】打卡第6天:第31~35题⛅前言员工的直属部门🔒题目🔑题解 判断三角形🔒题目🔑题解 连续出现的数字🔒题目🔑题解 指定日期的产品价格🔒题目&am…

通讯网关软件021——利用CommGate X2OPC实现OPC客户端访问Modbus设备

本文介绍利用CommGate X2OPC实现OPC客户端连接Modbus设备。CommGate X2OPC是宁波科安网信开发的网关软件,软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示,SCADA系统上位机、PLC、设备具备Modbus通讯接口,上位机…

工程物料管理信息化建设(十二)——关于工程物料管理系统最后的思考

目录 1 功能回顾1.1 MTO模块1.2 请购模块1.3 采购模块1.4 催交模块1.5 现场管理模块1.6 数据分析和看板模块1.7 其它模块 2 最后几个问题2.1 按管线发料和直接发料重叠2.2 YHA 材料编码的唯一性问题2.3 “合同量单-箱单-入库单” 数据映射 3 关于未来的思考3.1 三个专业之间的关…

单点接地、多点接地、混合接地

有三种基本的信号接地方式:浮地、单点接地、多点接地。 浮地:目的是使电路或设备与公共地线可能引起环流的公共导线隔离起来,浮地还使不同电位的电路之间配合变得容易。缺点:容易出现静电积累引起强烈的静电放电。折中方案:接入泄…

基于小波变换的分形信号r指数求解算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 ................................................................... %通过功率谱密度曲线…

Java数据结构第十九章、手撕图+最小生成树

一、图的基本概念 图是由顶点集合及顶点间的关系组成的一种数据结构:G = (V, E),其中:顶点集合V = {x|x属于某个数据对象集}是有穷非空集合;E = {(x,y)|x,y属于V}或者E = {<x, y>|x,y属于V && Path(x, y)}是顶点间关系的有穷集合,也叫做边的集合。(x, y)表…

c#设计模式-行为型模式 之 迭代器模式

&#x1f680;简介 提供一个对象来顺序访问聚合对象中的一系列数据&#xff0c;而不暴露聚合对象的内部表示。 迭代器模式主要包含以下角色&#xff1a; 抽象聚合&#xff08;Aggregate&#xff09;角色&#xff1a;定义存储、添加、删除聚合元素以及创建迭代器对象的接口…

flask vue跨域问题

问题&#xff1a; 调试时候跨域访问报&#xff1a; Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response. 解决办法&#xff1a; 安装flask_cros from flask_cors import CORS CORS(app) app.after_request def a…

linux用户管理,用户权限命令详解

一.用户管理 Linux 同时可以支持多个用户&#xff0c;每个用户对自己的文件设备有特殊的权利&#xff0c;能够保证用户之间互不干扰,就像手机开了助手一样&#xff0c;同时登陆多个 qq 账号&#xff0c;当硬件配置非常高时&#xff0c;每个用户还可以同时执行多个任务&#xf…

Langchain 代理 (Agents) ,赋能超级 LLMs

原文&#xff1a;Langchain 代理 (Agents) &#xff0c;赋能超级 LLMs - 知乎 大型语言模型&#xff08;LLMs&#xff09; 非常强大&#xff0c;但它们缺乏“最笨”的计算机程序可以轻松处理的特定能力。逻辑、计算和搜索是计算机通常擅长的领域&#xff0c;但 LLMs 却遇到了困…

上个月Balada Injector攻击中有超过17,000个WordPress网站被黑

导语 最近&#xff0c;一场名为Balada Injector的攻击活动引起了广泛关注。这次攻击以WordPress网站为目标&#xff0c;据统计&#xff0c;有超过17,000个网站受到了感染。在本文中&#xff0c;我们将详细介绍这次攻击的概述、攻击手段以及如何保护自己的网站。 攻击概述 Balad…

HTTP/2 中的漏洞

另一个热门漏洞是 CVE-2023-44487。 该漏洞与 HTTP/2 协议实施中的一个缺陷有关&#xff0c;可用于实施 DDoS 攻击。使用该漏洞的攻击被命名为 HTTP/2 快速重置。 为什么它很危险 要利用该漏洞&#xff0c;攻击者需要在 HTTP/2 会话中打开大量请求&#xff0c;然后在不等待服…

什么是Python虚拟环境?

视频教程地址&#xff1a;https://www.bilibili.com/video/BV1Zy4y1F7hC/ 大家好&#xff0c;这一集我们来介绍一下什么是Python虚假环境。虚拟环境是python基础知识中非常重要的一个知识点。 相信python新手都会遇到过这样的问题&#xff0c;在命令行中下载了某个三方库在py…

graphviz 绘制红黑树

代码 digraph RedBlackTree {node [fontname"Arial", shapecircle, stylefilled, color"#ffffff", fillcolor"#ff0000", fontsize12, width0.5, height0.5];edge [fontname"Arial", fontsize10, color"#333333", arrowsize…

竞赛抢答器4路抢答器verilog,仿真视频、代码、AX301开发板

名称&#xff1a;数字式竞赛抢答器设计4路抢答器verilog 软件&#xff1a;Quartus 语言&#xff1a;Verilog 代码功能&#xff1a; 数字式竞赛抢答器设计 设计一个可容纳四组参赛者同时抢答的数字抢答器。 要求&#xff1a; &#xff08;1&#xff09;能判断第一抢答者并…