Go语言学习Day4:函数(上)

名人说:莫愁千里路,自有到来风。 ——钱珝
创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)

目录

      • 1、函数的概念与定义
        • ①函数的概念
        • ②函数的具体定义
        • ③多返回值
      • 2、函数参数与作用域
        • ①可变参数
        • ②形式参数与实际参数
        • ③参数的传递细节
        • ④函数作用域
        • ⑤递归函数
      • 3、小结

1、函数的概念与定义

①函数的概念

在Go语言中,函数是基本的代码块,用于执行一个任务。函数可以接受输入参数,并且可以返回一个或多个值。它们是组织和复用代码的基本单位。在Go中,函数也可以被当作变量,传递给其他函数,或者从其他函数返回。

②函数的具体定义

函数的定义包括函数名、参数列表、返回值列表和函数体。格式如下:

//func 函数名 (参数1 类型1,参数2 类型2...)(返回值类型)
func functionName(param1 type1, param2 type2) (returnType) {
    // 函数体
}

案例1:自定义sub函数,并通过样例测试

//创作者:Code_流苏(CSDN)
package main

import "fmt"

func sub(x int, y int) int {
    return x - y
}

func main() {
    result := sub(6, 5)
    fmt.Println("6 - 5 =", result)
}

image-20240326223222601

案例2:加法,函数调用探析

package main

import "fmt"

/*
函数是基本的代码块,用于执行一个任务
*/
//main()主函数 程序的入口
func main() {
    var x int
    var y int
    var z int
    fmt.Println("请输入x和y的值:")
    fmt.Scanf("%d%d", &x, &y)
    //调用函数 函数名()
    z = add(x, y)
    fmt.Println(z)
}

//函数格式
//func 函数名(参数1,参数2...,参数类型) 返回值类型 {
//  函数体
//  return 返回值
//}

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

image-20240326223332933

③多返回值

Go语言支持函数返回多个值,这在处理错误或者需要返回多种数据时非常有用。

案例1:交换打印

package main

import "fmt"

func swap(x, y string) (string, string) {
    return y, x
}

func main() {
    a, b := swap("hello", "world")
    fmt.Println(a, b)
}

image-20240326223429825

案例2:函数调用,多返回值

package main

import "fmt"

func main() {
	//函数的调用
	printinfo()

	myprint("haha")

	c := add2(2, 3)
	myprintnum(c)

	x, y := swap("yueliusu", "you do it!")
	fmt.Println(x, y)
}

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

// 有一个参数的函数
func myprint(msg string) {
	fmt.Println(msg)
}

func myprintnum(x int) {
	println(x)
}

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

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

image-20240326223622407

2、函数参数与作用域

①可变参数

在Go语言中,函数的参数数量可以是可变的,称为可变参数。通过在参数类型前加上...符号来表示。

案例1:求和

package main

import "fmt"

func sum(nums ...int) {
    total := 0
    for _, num := range nums {
        total += num
    }
    fmt.Println(total) 
}

func main() {
    sum(1, 2)
    sum(1, 2, 3)
}

image-20240326224548809

案例2:不同参数

package main

import "fmt"

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

//在Go中,可变参数通过在参数类型前加上省略号 ... 来指定。
//这种参数在函数内部表现为同类型的切片(slice)。

// 参数 ...参数类型 <------> 可变参数
func getSum(msg string, nums ...int) {
	fmt.Println(msg)
	sum := 0

	for i := 0; i < len(nums); i++ {
		fmt.Println(nums[i])
		sum += nums[i]
	}

	fmt.Println("sum:", sum)
}

//若一个函数的参数有可变参数的同时还有其它参数,可变参数要放参数列表最后的位置
//一个函数的参数列表最多只能有一个可变参数
②形式参数与实际参数
  • 形式参数

    定义函数时,用于接收外部传入值的变量称为形式参数。(接收到)

  • 实际参数

    在调用函数时,传递给函数的实际值或变量称为实际参数。(传递给)

package main

func main() {
    // 形参与实参要一一对应,顺序,个数,类型
    // 实际参数
    println(max(1, 2))
}

//形式参数:定义函数时,用于接收外部传入值的 变量 称为形式参数
//实际参数:在调用函数时,传递给函数的实际值或变量称为实际参数

// max函数,实现两个数值比较大小
// 形式参数
func max(num1, num2 int) int {
    var result int
    if num1 > num2 {
       result = num1
    } else {
       result = num2
    }

    //函数定义时有说明返回值的类型,那么函数中必须使用return语句来返回值
    return result
}

image-20240326224206897

③参数的传递细节

Go语言中函数的参数是通过值传递的,这意味着函数接受的是参数值的一个副本。但是,如果参数是指针、切片或映射等引用类型,则函数可以修改原始数据。

  • 引用传递 ( 切片 )

    引用传递 操作的是数据的地址 如:slice、map、chan…

  • 值传递 ( 数组 )

    值传递 操作的是数据本身 如:基础数据类型int、string、bool、floa64、array、struct…

案例1:引用传递,数据修改

package main

import "fmt"

func modify(s []int) {
    s[0] = 100
}

func main() {
    a := []int{1, 2, 3}
    modify(a)
    fmt.Println(a) // 输出 [100, 2, 3],原始数据被修改
}

image-20240326224746713

案例2:值传递,接收与修改数据

package main

import "fmt"

func main() {
    //值传递

    arr := [4]int{1, 2, 3, 4}
    fmt.Println(arr)

    //值传递:拷贝实际参数arr的值给形式参数arr2
    update(arr)
    fmt.Println("调用函数后数据被修改为:", arr)
    //调用函数后,arr中的数据并未发生变化,说明是值传递
    //修改arr2的值并不会影响到arr的值
    //值传递:传递的是数据的副本,此时修改副本的数据,对原数据并不影响,究其根本在于二者并不在同一内存空间

    //引用传递
    //见下个案例
}

//值传递 操作的是数据本身 如:基础数据类型int、string、bool、floa64、array、struct...
//引用传递 操作的是数据的地址 如:slice、map、chan...

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

image-20240326224920045

案例3:引用传递,切片

package main

import "fmt"

func main() {
    //定义一个切片
    s1 := []int{1, 2, 3, 4}
    fmt.Println("s1默认数据", s1)
    update2(s1)
    fmt.Println("调用函数后s1的数据为:", s1)

}

//引用传递,传递的是数据的地址,当修改该数据时,由于和原数据共处同一地址处,原数据也会随着修改

func update2(s2 []int) {
    fmt.Println("s2 接收到的数据为:", s2)
    s2[0] = 10
    fmt.Println("s2[0]被修改后,s2的数据为:", s2)
}

image-20240326225156187

④函数作用域

变量的作用域是程序中变量可以正常访问的范围。在Go中:

  • 局部变量

    函数内定义的变量,它只在函数体内部或语句块内部可见。

  • 全局变量

    函数外部定义的变量。

案例1:内部与外部

package main

import "fmt"

func main() {
    x := "outside"
    {
        y := "inside"
        fmt.Println(y) // 输出 inside
    }
    fmt.Println(x) // 输出 outside
    // fmt.Println(y) // 编译错误:y在这里不可见
}

image-20240326225358932

案例2:局部变量,就近原则

package main

import "fmt"

var num int = 50

// 全局变量是 在函数外部定义的 变量
// 局部变量是 在函数内或语句块内定义的 变量 。它们只能在其定义的函数或语句块内部被访问。
func main() {

    //函数体内的局部变量
    temp := 100

    if b := 1; b <= 10 {
       //语句体内的局部变量
       temp := 50
       fmt.Println(temp) //局部变量 遵循就近原则

       fmt.Println(b)
    }
    fmt.Println(temp)

    fmt.Println(num)

    f1()
    f2()
}

func f1() {
    num := 40
    fmt.Println(num)
}

func f2() {
    fmt.Println(num)
}
⑤递归函数

递归函数是指一个函数在其定义中调用自己的函数。递归允许程序以简洁的方式解决复杂问题,在数据量小的时候,使用递过来实现是十分简便的,但是若数据量较大,不建议再使用递归函数来解决,因为这会占用太大的空间,程序效率较低。

因此,总结一下,使用递归时,一般需要注意以下几点:

  1. 确保有终止条件:递归函数必须有一个明确的终止条件,否则会无限递归下去,导致栈溢出错误。终止条件通常是一个或多个基案(base case),即最简单的问题实例,可以直接解答,不需要进一步递归。
  2. 注意栈空间的使用:每次函数调用时,都会在栈上为其分配空间来保存参数、局部变量和返回地址等信息。递归调用过深可能会耗尽栈空间,导致栈溢出。因此,对于可能导致深层递归的问题,需要谨慎设计递归逻辑,或考虑使用迭代等其他方法。
  3. 递归深度限制:在某些情况下,特别是处理大数据量或深度嵌套的数据结构时,考虑设置递归深度限制,以避免可能的栈溢出或过度消耗资源。

案例1:递归求阶乘

package main

import "fmt"

func factorial(n int) int {
    if n == 0 {
        return 1
    }
    return n * factorial(n-1)
}

func main() {
    fmt.Println(factorial(5)) // 输出 120
}

image-20240326230402126

案例2:递归求和

image-20230209215533739

package main

import "fmt"

func main() {
    sum := Sum(5)
    fmt.Println(sum)
}

// 递归函数 函数自己调用自己
// 递归需要有出口,也就是边界条件,否则会无限调用下去,导致栈溢出,系统崩溃
func Sum(n int) int {
    if n == 1 {
       return 1
    }
    return Sum(n-1) + n
}

image-20240326230529889

3、小结

  • 什么是函数?函数定义
  • 多个返回值的函数
  • 多个参数、可变参数 …
  • 参数的作用域( 小范围的可以用大范围的变量,反之则不行 )
  • 递归函数(函数自己调用自己,可能会导致栈溢出 … ,需要有终止条件或限制)

很感谢你能看到这里,如有相关疑问,还请下方评论留言。
Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)
希望本篇内容能对大家有所帮助,如果大家喜欢的话,请动动手点个赞和关注吧,非常感谢你们的支持!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

windows安装tomcat

安装之前需要安装jdk1.8可以参考windows安装jdk1.8-CSDN博客 一、下载tomcat Apache Tomcat - Apache Tomcat 8 Software Downloads 解压到D盘的D:\Program Files\tomcat目录下 二、配置环境变量 电脑右键属性-高级系统设置-高级-环境变量 1、在系统变量配置CATALINA_HOME环…

[flask]请求全局钩子

flask从入门到精通之钩子、异常、context、jinjia模板、过滤器 - 异步非阻塞 - 博客园 (cnblogs.com) 参考的这个博客&#xff0c;但有一个需要注意的是&#xff0c;最新版本的flask不知道是不是更新了还是怎么了&#xff0c;他的before_first_request不见了&#xff0c;如果继…

鸿蒙HarmonyOS 开发如果实现多端协同?

多端协同流程 多端协同流程如下图所示。 图1 多端协同流程图 约束限制 由于“多端协同任务管理”能力尚未具备&#xff0c;开发者当前只能通过开发系统应用获取设备列表&#xff0c;不支持三方应用接入。 多端协同需遵循 分布式跨设备组件启动规则 。 为了获得最佳体验&…

迭代实现二叉树的遍历-算法通关村

迭代实现二叉树的遍历-算法通关村 理论上&#xff0c;递归能做的迭代一定能做&#xff0c;但可能会比较复杂。有时候面试官要求不使用递归实现三种遍历&#xff0c;递归就是每次执行方法调用都会先把当前的局部变量、参数值和返回地址等压入栈中&#xff0c;后面在递归返回的时…

uniapp 使用命令行创建vue3 ts 项目

命令行创建 uni-app 项目&#xff1a; vue3 ts 版 npx degit dcloudio/uni-preset-vue#vite-ts 项目名称注意 Vue3/Vite版要求 node 版本^14.18.0 || >16.0.0 如果下载失败&#xff0c;请去gitee下载 https://gitee.com/dcloud/uni-preset-vue/repository/archive/vite-ts…

基于nodejs+vue的Spark的共享单车数据存储系统的设计与实现python-flask-django-php

本文拟采用nodejs技术和express搭建系统框架&#xff0c;后台使用MySQL数据库进行信息管理&#xff0c;设计开发的共享单车数据存储系统。通过调研和分析&#xff0c;系统拥有管理员和用户两个角色&#xff0c;主要具备个人中心、用户管理、共享单车管理、系统管理等功能模块。…

力扣爆刷第105天之CodeTop100五连刷11-15

力扣爆刷第105天之CodeTop100五连刷11-15 文章目录 力扣爆刷第105天之CodeTop100五连刷11-15一、5. 最长回文子串二、33. 搜索旋转排序数组三、102. 二叉树的层序遍历四、200. 岛屿数量五、121. 买卖股票的最佳时机 一、5. 最长回文子串 题目链接&#xff1a;https://leetcode…

Unity VisionOS开发流程

Unity开发环境 Unity Pro, Unity Enterprise and Unity Industry 国际版 Mac Unity Editor(Apple silicon) visionOS Build Support (experimental) 实验版 Unity 2022.3.11f1 NOTE: 国际版与国服版Pro账通用&#xff0c;需要激活Pro的许可证。官方模板v0.6.2,非Pro版本会打…

微软开源项目Garnet:Redis的竞争者还是替代者?

对于开源社区&#xff0c;最近的一大新闻就是Redis宣布从7.4版本开始&#xff0c;将采用Redis源代码可用许可证&#xff08;RSALv2&#xff09;和服务器端公共许可证&#xff08;SSPLv1&#xff09;的双重许可证&#xff0c;取代原有的BSD三条款许可证。这一变化引发了开发者社…

【P1328】[NOIP2014 提高组] 生活大爆炸版石头剪刀布

[NOIP2014 提高组] 生活大爆炸版石头剪刀布 题目背景 NOIP2014 提高组 D1T1 题目描述 石头剪刀布是常见的猜拳游戏&#xff1a;石头胜剪刀&#xff0c;剪刀胜布&#xff0c;布胜石头。如果两个人出拳一样&#xff0c;则不分胜负。在《生活大爆炸》第二季第 8 集中出现了一种…

Google AI 肺癌筛查的计算机辅助诊断

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

搭建Hadoop HA

目录 前言 搭建前准备 搭建 前言 Hadoop是一个由Apache基金会所开发的分布式系统基础架构&#xff0c;它允许用户在不了解分布式底层细节的情况下开发分布式程序&#xff0c;充分利用集群的威力进行高速运算和存储。Hadoop主要解决大数据存储和大数据分析两大核心问题&…

Java/JSP界面实现多国语言支持,支持插入变量,还要考虑名词单复数

在Java/JSP中&#xff0c;通常使用.properties文件定义各语言的文本&#xff0c;里面可以用{0},{1},{2}表示待插入的变量值&#xff08;之所以用数字&#xff0c;不用%s、%d等占位符&#xff0c;是因为不同语言的语序不同&#xff09;。 用java.util.ResourceBundle类的Resourc…

javaWeb教务查询系统

一、简介 在教育管理领域&#xff0c;教务管理系统是一个至关重要的工具&#xff0c;它能够有效地协调学校、教师和学生之间的各种活动。我设计了一个基于JavaWeb的教务管理系统&#xff0c;该系统包括三个角色&#xff1a;管理员、教师和学生。管理员拥有课程管理、学生管理、…

深度理解文件操作

目录 文件 文件名&#xff1a; 标准流 文件指针 文件的打开和关闭 文件的顺序读写&#xff1a; 使用部分 文件的打开和关闭 文件 文件分两种&#xff0c;第一种是程序文件&#xff0c;后一种是数据文件。 程序文件&#xff1a;包括源程序文件&#xff08;后缀为.c&…

Web APIs 学习知识总结

渲染学成在线案例 html文件: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Com…

聊聊k8s服务发现的优缺点

序 本文主要研究一下使用k8s服务发现的优缺点 spring cloud vs kubernetes 这里有张spring cloud与kubernetes的对比&#xff0c;如果将微服务部署到kubernetes上面&#xff0c;二者有不少功能是重复的&#xff0c;可否精简。 这里主要是讲述一下如果不使用独立的服务发现&am…

代码学习记录28----贪心算法

随想录日记part28 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.26 主要内容&#xff1a;今天深入学习贪心算法&#xff0c;接下来是针对题目的讲解&#xff1a;1.柠檬水找零 &#xff1b;2. 根据身高重建队列&#xff1b;3.用最少数量的箭引爆气球 860.柠…

Jmeter压测实战:Jmeter二次开发之自定义函数

1 前言 Jmeter是Apache基金会下的一款应用场景非常广的压力测试工具&#xff0c;具备轻量、高扩展性、分布式等特性。Jmeter已支持实现随机数、计数器、时间戳、大小写转换、属性校验等多种函数&#xff0c;方便使用人员使用。如果在使用过程中存在和业务强耦合的常用功能函数…

数据结构与算法分析引论1

1.解决问题的算法有很多&#xff0c;但是在输入不同的情况下&#xff0c;不同算法之间的差异也很大&#xff0c;我们总是追求一个更快、更有效的方法。比如说普通的依次查找和二分查找&#xff0c;两者的差异就很大。我们使用大O表示法来表示算法的速度。依次查找就是O(n)&…