[Go语言快速上手]函数和包

news/2024/12/22 9:07:07/

目录

一、Go中的函数

函数声明

 多个返回值

可变参数

匿名函数

值传递和地址传递

函数执行顺序(init函数)

二、Go中的包

基本语法

主要包(main package)

导入其他包

包的作用域

包的使用

包名别名

小结


一、Go中的函数

        Go中的函数与其他函数中功能大差不差,只是格式不同,当然也更加简便,从中可以看到其他语言的影子,但是开发效率会高上不少。

函数声明

  • 函数签名:函数的声明包括函数名、参数列表和返回类型。
  • 参数:可以在函数定义中指定参数的名字和类型。
  • 返回值:可以指定函数返回的类型。如果函数不需要返回任何值,可以使用 () 表示无返回值。

一个简单的Go函数定义如下:

package mainimport "fmt"// 定义一个名为 add 的函数,接受两个 int 参数,返回一个 int 结果
func add(a int, b int) int {return a + b
}func main() {// 调用 add 函数result := add(2, 3)fmt.Println("结果是:", result)
}

 多个返回值

我们的返回值列表也可以设置多返回值,这个C++中可能就要设置自定义数据类型或者模板来实现,而Go提供了很便捷的方法,直接定义返回值列表返回即可

func divide(a int, b int) (int, error) {if b == 0 {return 0, fmt.Errorf("除数不能为零")}return a / b, nil
}func main() {result, err := divide(10, 2)if err != nil {fmt.Println("错误:", err)} else {fmt.Println("结果是:", result)}
}

可变参数

如果你想要传递可变数量的参数给一个函数,可以使用 ... 操作符

func sum(nums ...int) int {total := 0for _, num := range nums {total += num}return total
}func main() {result := sum(1, 2, 3, 4, 5)fmt.Println("总和是:", result)
}

匿名函数

你也可以定义匿名函数,并将其赋值给一个变量或立即调用:

func main() {sum := func(nums ...int) int {total := 0for _, num := range nums {total += num}return total}result := sum(1, 2, 3, 4, 5)fmt.Println("总和是:", result)
}

我们来看这一种情况,将函数赋值给一个变量,这个变量就是一个函数,和我们之前学习的函数指针非常像,回调函数的场景应用非常多


func test(args ...int) {//函数内部处理可变参数,将可变参数当作切片来处理for i := 0; i < len(args); i++ {fmt.Println(args[i])}
}
func test2(num1 int, num2 int, funct func(args ...int)) {funct(num1, num2)
}
func main() {//var a = 10//var b = 20//exchange(&a, &b)//fmt.Println(a)//fmt.Println(b)test(1, 2, 3, 4, 5, 6, 7, 8, 6, 55)c := testfmt.Printf("c:%T,test:%T\n", c, test)c(1, 2, 3, 5, 6, 7, 8)test2(1, 2, test) //test和C是完全一样的test2(1, 2, c)
}

 可以看到c和test的类型没有任何区别

值传递和地址传递

在C语言中我们直到形参的改变不会引起实参的改变,所以我们需要传递实参的地址 

package mainimport "fmt"func exchange(num1 *int, num2 *int) {var tmp int = *num1*num1 = *num2*num2 = tmp
}func test(args ...int) {//函数内部处理可变参数,将可变参数当作切片来处理for i := 0; i < len(args); i++ {fmt.Println(args[i])}
}
func test2(num1 int, num2 int, funct func(args ...int)) {funct(num1, num2)
}
func main() {var a = 10var b = 20exchange(&a, &b)fmt.Println(a)fmt.Println(b)test(1, 2, 3, 4, 5, 6, 7, 8, 6, 55)//c := testfmt.Printf("c:%T,test:%T", c, test)c(1, 2, 3, 5, 6, 7, 8)//test2(1, 2, test)//test2(1, 2, c)
}

函数执行顺序(init函数)

全局变量初始化:全局变量的初始化按其声明顺序进行。

包级别的 init 函数:每个包中的 init 函数按包的依赖顺序执行。

main 函数:一旦所有初始化完成,程序进入 main 包的 main 函数。

 下面是一个综合示例,展示了全局变量初始化、包级别的 init 函数和 main 函数的执行顺序

// pkg1/init.go
package pkg1var x = initX()func initX() int {println("初始化 pkg1.x")return 10
}func init() {println("pkg1 的 init 函数")
}// pkg2/init.go
package pkg2var y = initY()func initY() int {println("初始化 pkg2.y")return 20
}func init() {println("pkg2 的 init 函数")
}// main/main.go
package mainimport ("pkg1""pkg2"
)func main() {println("main 函数开始")println("pkg1.x 的值:", pkg1.x)println("pkg2.y 的值:", pkg2.y)
}

输出是

初始化 pkg1.x

pkg1 的 init 函数

初始化 pkg2.y

pkg2 的 init 函数

main 函数开始

pkg1.x 的值: 10

pkg2.y 的值: 20 

二、Go中的包

        在 Go 语言中,包(package)是一个重要的概念,用于组织和复用代码。通过使用包,你可以将相关的函数、类型、变量等组织在一起,从而提高代码的可维护性和可读性。

基本语法

每个 Go 文件必须属于一个包。包的声明位于文件的顶部:

package mypackage

其中 mypackage 是包的名称。通常,包名会反映其功能或用途(一般建议包名和文件夹名称相同)

主要包(main package)

一个特殊的包是 main 包,它是程序的入口点。当编译和运行一个 Go 程序时,默认情况下会编译 main 包。main 包中的 main 函数是程序执行的起点:

package mainimport "fmt"func main() {fmt.Println("Hello, world!")
}

导入其他包

你可以通过 import 语句来导入其他包。导入语句通常位于包声明之后,但在任何其他代码之前

如果导入多个包,可以使用这种写法更为便捷

import ("fmt"      // 标准库包"mypackage" // 自定义包
)

包的作用域

在 Go 中,包内的标识符(如变量、函数、类型等)默认具有包级作用域,这意味着它们只能在同一包内访问。为了使一个标识符在其他包中也能访问,需要将其首字母大写

package common// 大写的标识符在其他包中可访问
func Add(a int, b int) int {return a + b
}// 小写的标识符只在当前包中可访问
func add(a int, b int) int {return a + b
}

包的使用

我们来看一下下图,如果将所有函数都写在一个文件里那么会很难阅读,同时模块划分也会很混乱,所以我们可以把一些工具函数写在其他包中,在需要使用的地方导入包即可。

 我们可以使用这样一个简单的结构来测试

在main中调用common中的Add和db中的Getconn

package dbfunc Getconn() {println("数据库连接")println("dbutil函数执行")
}
package aaafunc Add(a int, b int) int {println("common_________")return a + b
}

main.go

package mainimport ("fmt""gocode/test_10_2/common""gocode/test_10_2/db"
)func main() {fmt.Println("main函数执行")db.Getconn()var c int = aaa.Add(1, 5)println(c)}

运行输出如下

那同名函数会冲突吗

 

我们在db中也定义一个Add调用,其实也不会冲突,因为需要使用导入的包名作为前缀来调用函数。//在 main 函数中,我们使用 aaa.Add 来调用 Add 函数。这里 aaa 是包名,Add 是函数名。

包名别名

如果导入的包名较长,或者为了避免与其他包名冲突,可以给包起一个别名,比如下面的例子我们就使用了test来当作包名,但是使用了test后就不能再使用原来的包名了

package mainimport ("fmt"test "gocode/test_10_2/common""gocode/test_10_2/db"
)func main() {fmt.Println("main函数执行")db.Getconn()var c int = test.Add(1, 5)println(c)var d int = db.Add(3, 4)println(d)
}

小结

        以上就是Go中一些函数和包的简单使用,在实际应用场景中可能更多的用法,就需要我们在这些基础上进行操作。函数是 Go 语言中非常灵活的构造,可以用来实现各种复杂的逻辑。合理地组织和使用包,可以使 Go 程序更加模块化和易于维护。确保遵循 Go 的最佳实践,如使用简洁的包名、导出必要的标识符等,可以使代码更加健壮和易用。


http://www.ppmy.cn/news/1534312.html

相关文章

面试准备111

Java基础 反射 集合 多线程 Synchronized/volatile 线程池 cas atomic 网络 tcp 三次握手/四次挥手 流量控制 拥塞控制 数据结构 算法 Spring 循环依赖 Mybatis 如何防止sql注入 Mysql 索引 索引分类 索引设计原则 事务 四种隔离级别 MVCC 日志 Binlog…

排序题目:翻转对

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二预备知识思路和算法代码复杂度分析 解法三预备知识思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;翻转对 出处&#xff1a;493. 翻转对 难度 8 级 题目描述 要…

通信工程学习:什么是IP网际协议

IP&#xff1a;网际协议 IP网际协议&#xff08;Internet Protocol&#xff0c;简称IP&#xff09;是整个TCP/IP协议栈中的核心协议之一&#xff0c;它负责在网络中传送数据包&#xff0c;并提供寻址和路由功能。以下是对IP网际协议的详细解释&#xff1a; 一、对IP网际协议的…

把白底照片变蓝色用什么软件免费 批量更换证件照底色怎么弄

作为专业的修图师&#xff0c;有时候也会接手证件照修图和换底色工作&#xff0c;这种情况下&#xff0c;需要换底色的照片也许达到上百张。为了提高工作效率&#xff0c;一般需要批量快速修图&#xff0c;那么使用什么软件工具能够给各式不同的照片批量更换背景色呢&#xff1…

自学网络安全(黑客技术)90天学习计划

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 前言 什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”…

绘制随k变化的等熵面积比公式

xmax 4; Ma 0.1:0.05:xmax; figure; hold on; xlim([0,xmax]); ylim([0,10]);% 预定义k值的向量 k_values 1.2:0.1:1.4;% 创建一个细胞数组来存储图例标签 legendStrings cell(1, length(k_values));% 绘制每条曲线并记录图例标签 lines []; for idx 1:length(k_values)k…

项目-坦克大战学习笔记-绘制坦克

在上一节我们绘制地图的时候调用了gudin类存储参数&#xff0c;现在我&#xff0c;需要绘制玩家就需要调用wanjia类中的参数 首先&#xff0c;我们在玩家类中声明一个构造函数&#xff0c;需要传参的有坐标和速度&#xff0c;在里面默认设置玩家坦克4个方向的图片对象以及默认…

使用 classification_report 评估 scikit-learn 中的分类模型

介绍 在机器学习领域&#xff0c;评估分类模型的性能至关重要。scikit-learn 是一个功能强大的 Python 机器学习工具&#xff0c;提供了多种模型评估工具。其中最有用的函数之一是 classification_report&#xff0c;它可以全面概述分类模型的关键指标。在这篇文章中&#xff…