Go语言函数详解

这篇具有很好参考价值的文章主要介绍了Go语言函数详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

函数

(1)函数的定义

  • 函数使用func进行定义
  • 函数是基本的代码块,用于执行一个任务
  • Go语言至少有一个main函数
  • 函数声明告诉了编译器函数的名称,返回类型和参数
//1.无参数无返回值函数的定义
func test1(){
    fmt.Println("无参数无返回值函数的定义\n")
}

//2.有参数无返回值函数的定义
func test2(str string){
    fmt.Println("有参无返回值:%s\n",str)
}

//3.多参无返回值
func test3(a,b int) int{
    return a+b
}

//4.多个返回值
func test4(a,b int) (int,int){
    return a,b
}

//函数的调用
fun main()
{
    test1()
    test2("WY")
    test3(1,2)
    test4(5,6)
    
}

(2)函数的可变参数

  • 一个函数的参数类型确定,但个数不确定时可以使用可变参数
  • 定义可变参数时,使用**... **符号
  • 可变参数本质上是保存到了一个数组当中
  • 注意:可变参数要放在参数定义的最后;一个函数的参数列表最多只有一个可变参数
//可变参数函数定义
func add_sum(num...int){
    sum := 0
    for _,i := range num{
        sum += num[i-1]
    }
}

(3)参数传递的类型

  • 参数分为两种类型:

    • 值类型-操作的是数据本身,例如我们常用的:int,string,bool,float64,array
    • 引用类型的数据-操作的是数据的地址:例如slice,map,chan
  • 值传递在调用完函数后不会修改原本值传递参数的值

//定义一个函数,进行值传递实验
func update(arr2 [4]int){
    fmt.Println("arr2接收到的数据:"arr2)        
    arr2[0] = 100
    fmt.Println("arr2修改后的数据:"arr2)
}

//定义主函数,调用update进行值传递观察
func main(){
    arr := [4]int{1,2,3,4}    //定义一个数组
    fmt.Println(arr)
    //传递值
    update(arr)
    fmt.Println("调用后的数据")     //这里的结果为[1,2,3,4]
}

  • 引用类型数据的参数传递在调用完函数后会修改原本值传递参数的值
package main

import "fmt"

/*
=====引用传递=======
1、定义一个切片
2、通过方法修改切片里面的数据
3、打印输出修改后值
*/
func main() {
	arr := []int{1, 2, 3, 4}       //定义一个切片
	fmt.Println("调用修改前的数据", arr)
	updata2(arr)
	fmt.Println("调用修改后的数据", arr)
}
func updata2(arr []int) {
	fmt.Println("arr接受的数据:", arr)
	arr[0] = 100
	fmt.Println("arr修改后的数据:", arr)
}
/*
调用修改前的数据 [1 2 3 4]
arr接受的数据: [1 2 3 4]
arr修改后的数据: [100 2 3 4]
调用修改后的数据 [100 2 3 4]
*/

(4)函数变量的作用域

  • 作用域:变量可以使用的范围
  • 局部变量:函数内部定义的变量,叫做局部变量,只能在定义该变量的函数内使用
  • 全局变量:函数外部定义的变量,叫做全局变量,可以在任何函数里面使用
package main

import "fmt"

// 全局变量  所有函数都可以使用
var num int = 30

func main() {
   // 局部变量 temp 只能在定义temp的方法中使用
   temp := 100

   if b := 1; b < 10 {
      temp := 30
      fmt.Println("局部变量b:", b)
      fmt.Println("局部变量temp:", temp)
   }
   fmt.Println(temp)

   // 调用f1,f2方法
   f1()
   f2()
}
func f1() {
   fmt.Println(num)
}
func f2() {
   fmt.Println(num)
}

(5)递归函数

  • 递归函数的定义:可以自己调用自己的函数
  • 递归函数必须要有一个出口,否则会陷入死循环
package main

import "fmt"

/*
1、创建一个求和函数 getsum
2、给递归函数一个出口
3、创建对象来接收函数
*/
func main() {
	//3、创建对象来接收函数
	sum := getSum(5)

	fmt.Println(sum)
}

//1、创建一个求和函数 getsum
func getSum(n int) int {

	//2、给递归函数一个出口
	if n == 1 {
		return 1
	}
	return getSum(n-1) + n
}

(6) defer延迟函数

  • defer函数可以延迟一个函数的执行

在以下代码块中,控制台打印的结果是1 2 4 3,因为defer将f(3)延迟到最后执行了

package main

import "fmt"

func main() {

   f("1")
   f("2")
   defer f("3")           //将该函数延迟到最后执行
   f("4")
}
func f(s string) {
   fmt.Println(s)
}

  • 如果使用了多个defer语句,则函数执行到最后时,这些defer语句会按照逆序执行
package main

import "fmt"

func main() {

   f("1")
   f("2")
   defer f("3")
   f("4")
   defer f("5")
   f("6")
   defer f("7")
   f("8")
}
func f(s string) {
   fmt.Println(s)
}
/*
输出结果:
1
2
4
6
8
7
5
3
*/

(7)func数据类型详解

  • 在go语言中,函数是复合类型,本质上可以看作是一个特殊的变量

  • func本身就是一个数据类型,func定义的函数之间可以相互赋值

package main

import "fmt"

/*
fun本身就是一个数据类型
1、创建一个函数
2、在mian方法定义相同类型的函数
3、将定义后的函数赋值个另一个函数
*/
func main() {
	//2、在mian方法定义相同类型的函数
	var fg func(int, int)

	//3、将定义后的函数赋值个另一个函数
	fg = ff              //将fg函数定义为ff函数相同的功能
	fg(1, 2)             //最后输出的结果为 1   2

}

//1、创建一个函数
func ff(a, b int) {
	fmt.Println(a, b)
}



(8)匿名函数

  • 什么是匿名函数:匿名函数就是没有名字的函数

匿名函数的创建

//这就是一个匿名函数,但如果直接放在代码块中不调用则编译器会报错
func() {
    fmt.Println("匿名函数")
}

//带参匿名函数
func(a,b int){
    fmt.Println("带参匿名函数")    
}

//带参且具有返回值函数
func(a,b int) int{
    fmt.Println("带参和返回值匿名函数")
    return a+b
}

匿名函数多种调用方式

func main(){
    
    //方式1:用一个变量调用匿名函数
    f3 := func(){
        fmt.Println("匿名函数的调用方式1")
    }
    f3() //调用匿名函数
    
    //方式2:创建匿名函数后直接调用func(),在{}后直接添加()进行调用
    func(){
        fmt.Println("匿名函数调用方式2")
    }()
    
    //带参匿名函数的调用
    func(a,b int){
        fmt.Println("带参匿名函数调用")
    }(1,2)    
    
    //带参和返回值匿名函数调用
    f5 := func(a,b int) int{
        fmt.Println("带参和返回值匿名函数")
        return a+b
    }(1,2)    
    fmt.Println(f5)     //打印调用结果
    
}

(9)高阶函数和回调函数

  • 回调函数:将一个函数作为另一个函数的参数

  • 若将fun1函数作为fun2函数的参数,则fun2叫做高阶函数,fun1称为回调函数文章来源地址https://www.toymoban.com/news/detail-711161.html

package main

import "fmt"

//1、创建一个高阶函数oper,传如一个函数类型的参数且有返回值
func oper(a, b int, fun func(int, int) int) int {
	r2 := fun(a, b)
	return r2
}

//2.创建其他方法的函数
func add(a, b int) int {
	return a + b
}

//创建其他方法的函数
func sub(a, b int) int {
	return a - b
}

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

	//3、调用高阶函数时,传入其他方法的函数
	r3 := oper(3, 4, add)
	fmt.Println(r3)
	r4 := oper(8, 4, sub)
	fmt.Println(r4)
}





(10)闭包

  • 一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量并且该外层函数的返回值就是这个内层函数
  • 这个内层函数和外层函数的局部变量,统称为闭包结构。
  • 局部变量的生命周期就会发生改变,正常的局部变量会随着函数的调用而创建,随着函数的结束而销毁但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还在继续使用
package main

import "fmt"

// 定义一个闭包函数。func() int是局部变量和返回值fun的类型
func increment() func() int {

	//局部变量
	i := 0
	//定义一个匿名函数 给变量自增并返回
	fun := func() int {
		//内层函数,没有执行
		i++
		return i
	}
	return fun
}

func main() {
	//定义一个变量 接受返回值(函数)
	r1 := increment()      //创建函数
	fmt.Println(r1)       //这里打印的是地址,因为r1还没有执行

	v1 := r1()
	fmt.Println(v1)
	//不断调用自增+1
	v2 := r1()
	fmt.Println(v2)
	//不断调用自增+1
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println(r1())
	fmt.Println("====================")
	//	==========================================================
	r2 := increment()      //创建函数,i也会清零
	v3 := r2()
	fmt.Println(v3)
	fmt.Println(r2())
	fmt.Println(r2())
	fmt.Println(r2())
	fmt.Println(r1())     //这里调用的是r1,因此i值还是原来r1的i值,这里自增后为7
	fmt.Println(r2())
}


/*
输出结果:
0xd5ea00
1
2
3
4
5
6
====================
1
2
3
4
7
5

*/

到了这里,关于Go语言函数详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Go 基础篇】Go语言 init函数详解:包的初始化与应用

    在Go语言中, init() 函数是一种特殊的函数,用于在包被导入时执行一次性的初始化操作。 init() 函数不需要手动调用,而是在包被导入时自动执行。这使得我们可以在包导入时完成一些必要的初始化工作,确保包的使用具有正确的环境和状态。 本篇博客将深入探讨 init() 函数

    2024年02月11日
    浏览(49)
  • 【Go 基础篇】Go语言结构体基本使用

    在Go语言中,结构体是一种重要的数据类型,用于定义和组织一组不同类型的数据字段。结构体允许开发者创建自定义的复合数据类型,类似于其他编程语言中的类。本文将深入探讨Go语言中结构体的定义、初始化、嵌套、方法以及与其他语言的对比,以便全面了解如何在Go中

    2024年02月10日
    浏览(42)
  • Go语言之 go-redis 基本使用

    Redis:https://redis.io/ Redis 中文网:https://www.redis.net.cn/ REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。 Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 它通常被称为

    2024年02月09日
    浏览(36)
  • 使用Go语言进行安卓开发

    本文将介绍如何使用Go语言进行安卓开发。我们将探讨使用Go语言进行安卓开发的优点、准备工作、基本概念和示例代码。通过本文的学习,你将了解如何使用Go语言构建高效的安卓应用程序。 随着移动互联网的快速发展,安卓应用程序的需求越来越旺盛。使用传统的Java和K

    2024年02月06日
    浏览(45)
  • 十、go语言Array(数组)基本使用方法

    Go 语言提供了数组类型的数据结构。 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整形、字符串或者自定义类型。 数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为 0,第二个索引

    2024年02月08日
    浏览(51)
  • Python 函数(lambda 匿名函数、自定义函数、装饰器)基本使用指南

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段 对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁; 对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。 格式: 一般形式 含 if

    2024年02月08日
    浏览(50)
  • 【go语言】2.4.2 自定义包的创建和使用

    在 Go 中,任何一个目录都可以被视为一个包。创建自定义包的基本步骤是: 新建一个目录,用于存放包的源文件。 在新建的目录中编写 Go 代码,代码的第一行应该是  package 包名 。 使用  import  语句在其他地方导入和使用这个包。 接下来,我们详细看一下如何创建和使用

    2024年02月15日
    浏览(43)
  • Fabric使用自己的链码进行测试-go语言

    书接前文 Fabric链码部署-go语言 通过上面这篇文章,你可以部署好自己的链码 (后面很多命令是否需要修改,都是根据上面这篇文章来的,如果零基础的话建议先看上面这篇) 就进行下一步 在测试网络上运行自己的链码 目录 1、导航到test-network目录 1.1 打开日志Logspout(可选

    2024年02月05日
    浏览(39)
  • 使用Go语言的HTTP客户端进行负载均衡

    负载均衡是分布式系统中的重要概念,它用于将流量分散到多个服务器或服务上,以实现更好的性能、可靠性和可扩展性。在Go语言中,可以使用HTTP客户端进行负载均衡,确保请求被均匀地分配到多个服务器或服务上。 下面是一个使用Go语言HTTP客户端进行负载均衡的示例:

    2024年01月21日
    浏览(47)
  • c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(下))

    上篇文章介绍了一些常用的字符串函数,大家可以跳转过去浏览一下:c语言进阶部分详解(详细解析字符串常用函数,并进行模拟实现(上))_总之就是非常唔姆的博客-CSDN博客 今天接着来介绍一些:  目录 一.字符串查找 1.strstr() 1.1示例 1.2注意事项: 1.3模拟实现  2.

    2024年02月07日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包