Go函数使用(函数定义、函数声明、函数调用等)

 更新时间:2023年11月20日 11:39:57   作者:hope_wisdom  
本文主要介绍了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 main
  
import "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)
    // 输出:300
    fmt.Println(sum)
    result, info := Process(188)
    // 输出:0 OK
    fmt.Println(result, info)
}

函数声明

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

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

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

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

函数调用

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

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

package main
  
import "fmt"

// 值传递
func Process1(number int) {
    number += 100
}

// 引用传递
func Process2(pNumber *int) {
    *pNumber += 100
}

func main() {
    number := 66
    Process1(number);
    // 输出:66
    fmt.Println(number)

    Process2(&number);
    // 输出:166
    fmt.Println(number)
}

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

package main
  
import "fmt"

func Calc(x, y int) (int, int) {
    return x + y, x * x + y * y
}

func main() {
    // 多个返回值,依次赋值
    sum, square := Calc(6, 8)
    // 输出:14 100
    fmt.Println(sum, square)

    // 使用占位符,忽略第一个返回值
    _, square2 := Calc(6, 8)
    // 输出:100
    fmt.Println(square2)
}

可变参数函数

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

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

package main

import "fmt"

func sum(numbers ...int) int {
    total := 0
    for _, value := range numbers {
        total += value
    }

    return total
}  

func main() {
    // 输出:300
    fmt.Println(sum(100, 200))

    // 输出:600
    fmt.Println(sum(100, 200, 300))
}

匿名函数

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

package main
  
import "fmt"

func main() {
    // 定义匿名函数
    add := func(a, b int) int {
        return a + b
    }

    result := add(66, 88)
    // 输出:154
    fmt.Println(result)
}

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

package main
  
import "fmt"

func main() {
    origin := 1000

    // 匿名函数可以访问外部变量
    add := func(a, b int) int {
        return a + b + origin
    }

    result := add(66, 88)
    // 输出:1154
    fmt.Println(result)
}

递归函数

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

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

package main

import "fmt"

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

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

高阶函数

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

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

package main

import "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)
    // 输出结果:165
    fmt.Println(result)

    result = ApplyFunc(Sub, 99, 66)
    // 输出结果:33
    fmt.Println(result)
}

 到此这篇关于Go函数使用(函数定义、函数声明、函数调用等)的文章就介绍到这了,更多相关Go函数使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go GCM gin中间件的加密解密文件流处理

    go GCM gin中间件的加密解密文件流处理

    这篇文章主要介绍了go语言 GCM加密解密,gin中间件的加密解密及文件流处理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2022-05-05
  • Golang的锁机制与使用技巧小结

    Golang的锁机制与使用技巧小结

    本文主要介绍了Golang的锁机制与使用技巧小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • Golang基础之函数使用(参数传值)实例详解

    Golang基础之函数使用(参数传值)实例详解

    这篇文章主要为大家介绍了Golang基础之函数使用(参数传值)实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • golang模板template自定义函数用法示例

    golang模板template自定义函数用法示例

    这篇文章主要介绍了golang模板template自定义函数用法,结合实例形式分析了Go语言模板自定义函数的基本定义与使用方法,需要的朋友可以参考下
    2016-07-07
  • 源码解析gtoken替换jwt实现sso登录

    源码解析gtoken替换jwt实现sso登录

    这篇文章主要为大家介绍了源码解析gtoken替换jwt实现sso登录的示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Go语言实现lru淘汰策略和超时过期

    Go语言实现lru淘汰策略和超时过期

    缓存的大小是有限的,当添加数据发现剩余缓存不够时,需要淘汰缓存中的部分数据,本文主要介绍了Go语言实现lru淘汰策略和超时过期,感兴趣的可以了解一下
    2024-02-02
  • Go语言应该什么情况使用指针

    Go语言应该什么情况使用指针

    go语言的指针类型和C/C++的指针类型用法是一样的,那么Go语言应该什么情况使用指针,本文就详细的介绍一下,感兴趣的可以了解一下
    2021-07-07
  • Golang源码分析之golang/sync之singleflight

    Golang源码分析之golang/sync之singleflight

    golang/sync库拓展了官方自带的sync库,提供了errgroup、semaphore、singleflight及syncmap四个包,本次先分析第一个包errgroup的源代码,下面这篇文章主要给大家介绍了关于Golang源码分析之golang/sync之singleflight的相关资料,需要的朋友可以参考下
    2022-11-11
  • Golang使用Gin框架实现HTTP响应格式统一处理

    Golang使用Gin框架实现HTTP响应格式统一处理

    在gin框架中,我们可以定义一个中间件来处理统一的HTTP响应格式,本文主要为大家介绍了具体是怎么定义实现这样的中间件的,感兴趣的小伙伴可以了解一下
    2023-07-07
  • Golang中下划线(_)的不错用法分享

    Golang中下划线(_)的不错用法分享

    golang中的下划线表示忽略变量的意思,也没有产生新的变量,但是后面的表达式依然会被执行,本文为大家整理了golang中下划线的一些不错的用法,需要的可以参考下
    2023-05-05

最新评论