• Go语言函数和包介绍


    函数

    什么是函数?

    函数是执行特定任务的代码块。函数接受输入,对输入执行一些计算,然后生成输出。

    通常每一个程序都包含有很多的函数,系统通过函数来划分不同功能,将整体任务进行分解。

    在 Go 语言中,函数的基本组成包括:关键字 func、函数名、参数列表、返回值、函数体和返回语句。

    Go 语言标准库提供了多种可动用的内置的函数。例如,len() 函数可以接受不同类型参数并返回该类型的长度。如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。

    函数声明

    在 go 中声明函数的语法是

    func functionname(parametername type) returntype {  
     //function body
    }
    
    • 1
    • 2
    • 3

    函数定义解析:

    • func:函数由 func 开始声明。
    • functionname:函数名称,函数名和参数列表一起构成了函数签名。
    • functionname type:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
    • returntype:返回类型,函数返回一列值。有些功能不需要返回值,这种情况下 returntype不是必须的。
    • 函数体:函数定义的代码集合。
    示例函数

    让我们编写一个函数,该函数将单个产品的价格和产品数量作为输入参数,并通过将这两个值相乘来计算总价格并返回输出。

    func calculateBill(price int, no int) int {  
        var totalPrice = price * no
        return totalPrice
    }
    
    • 1
    • 2
    • 3
    • 4

    上面的函数有两个 int 类型的输入参数priceno它返回的totalPrice是价格和编号的乘积。返回值也是int类型。

    如果连续的参数类型相同,就可以避免每次都写类型,最后写一次就可以了。即 price int, no int可以写为price, no int. 因此,上述函数可以重写为:

    func calculateBill(price, no int) int {  
        var totalPrice = price * no
        return totalPrice
    }
    
    • 1
    • 2
    • 3
    • 4

    现在我们已经准备好了一个函数,让我们从代码中的某个地方调用它。调用函数的语法是functionname(parameters)。可以使用代码调用上述函数。

    calculateBill(10, 5)  
    
    • 1

    这是使用上述函数并打印总价的完整程序。

    package main
    
    import (  
        "fmt"
    )
    
    func calculateBill(price, no int) int {  
        var totalPrice = price * no
        return totalPrice
    }
    
    func main() {  
        price, no := 90, 6
        totalPrice := calculateBill(price, no)
        fmt.Println("Total price is", totalPrice)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Run in playground

    上面的程序会打印

    Total price is 540  
    
    • 1
    多个返回值

    一个函数可以返回多个值。让我们编写一个函数rectProps,它接受矩形的 lengthwidth并返回

    长方形的面积->长和宽的乘积

    周长->长和宽之和的两倍

    package main
    
    import (  
        "fmt"
    )
    
    func rectProps(length, width float64)(float64, float64) {  
        var area = length * width
        var perimeter = (length + width) * 2
        return area, perimeter
    }
    
    func main() {  
         area, perimeter := rectProps(10.8, 5.6)
        fmt.Printf("Area %f Perimeter %f", area, perimeter) 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Run in playground

    如果函数返回多个返回值,则必须在(lengthwidth 它们之间指定)func rectProps(length, width float64)(float64, float64)有两个 float64 参数length and width并且还返回两个float64值。上面的程序打印出

    Area 60.480000 Perimeter 32.800000  
    
    • 1
    命名返回值

    可以从函数返回命名值。如果已命名返回值,则可以将其视为在函数的第一行中声明为变量。

    上面的 rectProps 可以使用命名的返回值重写为

    func rectProps(length, width float64)(area, perimeter float64) {  
        area = length * width
        perimeter = (length + width) * 2
        //无显式返回值
        return 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    面积周长是上述函数中的命名返回值。请注意,函数中的 return 语句不会显式返回任何值。由于 和 在函数声明中指定为返回值,因此在遇到 return 语句时会自动从函数返回它们。areaperimeter

    空白标识符

    **_**在 Go 中称为空白标识符。它可以代替任何类型的任何值。让我们看看这个空白标识符有什么用。

    该函数返回矩形的面积和周长。如果我们只需要 面积并想丢弃周长.这就是用处。area _

    参考下面的程序

    package main
    
    import (  
        "fmt"
    )
    
    func rectProps(length, width float64) (float64, float64) {  
        var area = length * width
        var perimeter = (length + width) * 2
        return area, perimeter
    }
    func main() {  
        area, _ := rectProps(10.8, 5.6) // perimeter is discarded
        fmt.Printf("Area %f ", area)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Run in playground

    Area 60.480000 
    
    • 1

    什么是包,为什么使用它们?

    到目前为止,我们已经看到 Go 程序只有一个包含一个 main函数和几个其他函数的文件。在现实场景中,这种将所有源代码写入单个文件的方法是不可扩展的。重用和维护以这种方式编写的代码变得不可能。这就是包的用处。

    包用于组织 Go 源代码,以提高可重用性和可读性。包是驻留在同一目录中的 Go 源文件的集合。包提供了代码划分,因此维护 Go 项目变得很容易。

    演示图例

    在这里插入图片描述

    Go 模块

    Go 模块只不过是 Go 包的集合。现在你可能会想到这个问题。为什么我们需要 Go 模块来创建自定义包?答案是我们创建的自定义包的导入路径派生自 go 模块的名称。除此之外,我们的应用程序使用的所有其他第三方软件包(例如来自 github 的源代码)将与版本一起出现在文件中。此文件是在我们创建新模块时创建的。您将在下一节中更好地理解这一点。

    cd learnpackage 目录下
    //执行
    go mod init learnpackage  
    
    • 1
    • 2
    • 3

    上面的命令将创建一个名为go.mod的文件,以下是文件的内容。

    module learnpackage
    
    go 1.21.0
    
    • 1
    • 2
    • 3

    我们创建simpleinterest文件夹,在创建一个simpleinterest.go文件

    package simpleinterest
    
    //计算并返回本金p的单利,利率r的时间跨度为t年
    func Calculate(p float64, r float64, t float64) float64 {  
        interest := p * (r / 100) * t
        return interest
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在上面的代码中,我们创建了一个计算并返回简单利息的函数Calculate。此功能是计算并返回单利。

    请注意,函数名称 Compute 以大写字母开头。这是必不可少的

    导入自定义包

    要使用自定义包,我们必须先导入它。导入路径是附加在包的子目录和包名称上的模块名称。在我们的例子中,模块名称是learnpackage,包在直接位于下面的文件夹中的simpleinterest
    目前项目目录:
    在这里插入图片描述

    导入simpleinterest
    在这里插入图片描述

    上面的代码导入包并使用函数查找单利。标准库中的包不需要模块名称前缀,因此“fmt”在没有模块前缀的情况下工作。当应用程序运行时,输出将是`

    Simple interest calculation  
    Simple interest is 500  
    
    • 1
    • 2
    初始化函数

    Go 中的每个包都可以包含一个函数。该函数不得具有任何返回类型,并且不得具有任何参数。init 函数不能在我们的源代码中显式调用。初始化包时将自动调用它。初始化函数具有以下语法init``init

    func init() {  
    }
    
    • 1
    • 2

    该函数可用于执行初始化任务,也可用于在执行开始之前验证程序的正确性。init

    包的初始化顺序如下

    1. 首先初始化包级变量
    2. 接下来调用初始化函数。包可以有多个 init 函数(在单个文件中或分布在多个文件中),并且按照它们呈现给编译器的顺序调用它们。

    如果包导入其他包,则首先初始化导入的包。

    即使从多个包导入包,也只会初始化一次包。

    让我们对应用程序进行一些修改以了解函数。init

    首先,让我们将函数添加到文件中。init``simpleinterest.go

    package simpleinterest
    
    import "fmt"
    
    /*
     * 新增Init功能
     */
    func init() {
    	fmt.Println("初始化  simpleinterest")
    }
    
    // 计算并返回本金p的单利,利率r的时间跨度为t年interest r for time duration t years
    func Calculate(p float64, r float64, t float64) float64 {
    	interest := p * (r / 100) * t
    	return interest
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    我们添加了一个简单的初始化函数

    现在让我们修改主包。我们知道,在计算单利时,本金、利率和持续时间应大于零。我们将在文件中使用 init 函数和包级变量来定义此检查。main.go

    将 修改为以下内容,main.go

    package main
    
    import (
    	"fmt"
    	"learnpackage/simpleinterest"
    )
    
    func init() {
    	fmt.Println("初始化  main")
    }
    
    var p, r, t = 5000.0, 10.0, 1.0
    
    func main() {
    	fmt.Println("简单利息计算")
    	si := simpleinterest.Calculate(p, r, t)
    	fmt.Println("单利是", si)
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    以下是对main.go

    1. PRT 变量从主函数级别移动到包级别。
    2. 添加了初始化函数。init 函数使用 log 打印日志并在本金、利率或持续时间小于零时终止程序执行**。致命**功能。

    初始化的顺序如下:

    1. 首先初始化导入的包。因此,首先初始化 simpleinterest 包,并调用它的 init 方法。
    2. 接下来初始化包级变量 prt
    3. 初始化函数在 main 中调用。
    4. 最后调用主函数。

    如果运行该程序,将获得以下输出。

    初始化  simpleinterest
    初始化  main
    简单利息计算
    单利是 500  
    
    • 1
    • 2
    • 3
    • 4
    使用空白标识符

    在 Go 中导入包而不在代码中的任何位置使用它都是非法的。如果您这样做,编译器将报错。这样做的原因是为了避免未使用的包膨胀,这将显着增加编译时间。将 main.go中的代码替换为以下内容,

    package main
    
    import (  
            "learnpackage/simpleinterest"
    )
    
    func main() {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    上述程序将出错

    # learnpackage
    ./main.go:4:2: imported and not used: "learnpackage/simpleinterest"
    
    • 1
    • 2

    但是,在应用程序处于积极开发状态时导入包并在以后(如果不是现在)在代码中的某个位置使用它们是很常见的。在这些情况下,空白标识符可以拯救我们。_

    package main
    
    import (  
        _ "learnpackage/simpleinterest"
    )
    
    func main() {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行上述程序将输出 。我们已经成功初始化了包,即使它没有在代码中的任何位置使用。

    在这里插入图片描述
    上一教程 Go语言常量介绍
    下一教程 Go语言条件语句

  • 相关阅读:
    jenkins2.289.1版本远程命令执行漏洞
    Linux下线程池(ThreadPool)
    JavaScript 中 Location 对象介绍
    用于实体和关系抽取的封装式悬空标记
    指针-成绩统计
    Spring MVC 源码分析
    vue中使用图像编辑器tui-image-editor(二)——应用示例
    【编程题】【Scratch一级】2022.06 报时的公鸡
    Leetcode 17. 电话号码的字母组合
    顶会框架整理-ICLR2024
  • 原文地址:https://blog.csdn.net/qq497811258/article/details/133813934