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

news2024/11/16 1:51:50

目录

一、Go中的函数

函数声明

 多个返回值

可变参数

匿名函数

值传递和地址传递

函数执行顺序(init函数)

二、Go中的包

基本语法

主要包(main package)

导入其他包

包的作用域

包的使用

包名别名

小结


一、Go中的函数

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

函数声明

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

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

package main

import "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 := 0
    for _, 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 := 0
        for _, 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 := test
	fmt.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 main

import "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 = 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 := test
	fmt.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 pkg1

var x = initX()

func initX() int {
    println("初始化 pkg1.x")
    return 10
}

func init() {
    println("pkg1 的 init 函数")
}

// pkg2/init.go
package pkg2

var y = initY()

func initY() int {
    println("初始化 pkg2.y")
    return 20
}

func init() {
    println("pkg2 的 init 函数")
}

// main/main.go
package main

import (
    "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 main

import "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 db

func Getconn() {
	println("数据库连接")
	println("dbutil函数执行")
}
package aaa

func Add(a int, b int) int {
	println("common_________")
	return a + b
}

main.go

package main

import (
	"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 main

import (
	"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.coloradmin.cn/o/2185148.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重生之我们在ES顶端相遇第 18 章 - Script 使用(进阶)

文章目录 0. 前言1. 基本使用2. 读请求中访问文档字段2.1 遍历 List2.2 判断对象存不存在2.3 判断值是否为空2.4 总结 3. 写请求中访问文档字段3.1 数字相加3.2 字符串相加3.3 将字符串转为数组 0. 前言 在前面部分&#xff0c;我们介绍了 ES 的基本使用和要掌握的基础性读写原…

TypeScript 算法手册【快速排序】

文章目录 1. 快速排序简介1.1 快速排序定义1.2 快速排序特点 2. 快速排序步骤过程拆解2.1 选择基准元素2.2 划分数组2.3 递归排序 3. 快速排序的优化3.1 三数取中法选择基准3.2 插入排序与快速排序结合案例代码和动态图 4. 快速排序的优点5. 快速排序的缺点总结 【 已更新完 Ty…

二分查找算法专题(1)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; 优选算法专题 目录 二分查找算法的介绍 704. 二分查找 34. 在排序数组中查找元素的第一个和 最后一个位置 35. 搜索插入位置 69. x的平…

10-指针和多维数组

多维数组&#xff0c;本质上是数组的数组&#xff1a; 一、多维数组&#xff1a; int B[2][3] int(*P)[3] B;Print B //400 Print *B; //400 Print B[0] //400 Print &B[0][0] // 400B[i][j] *(B[i]j) *(*(Bi)j); int C[3][2][2] int(*p)[2][2] C; Print C //800 Prin…

大数据开发--1.1大数据概论

目录 一.大数据的概念 什么是大数据&#xff1f; 二. 大数据的特点 三. 大数据应用场景 四. 大数据分析业务步骤 大数据分析的业务流程&#xff1a; 五.大数据职业规划 职业方向 岗位技术要求 六. 大数据学习路线 一.大数据的概念 什么是大数据&#xff1f; 数据 世界…

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第十六章 Linux 第一个程序 HelloWorld

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

LC记录二:丑数专题,一文秒解丑数3题

文章目录 263.丑数1264.丑数21201.丑数3 263.丑数1 https://leetcode.cn/problems/ugly-number/description/ 简单题&#xff0c;丑数只包含质因子2、3、5。所以直接使用 n 循环 除 2 3 5最后判断结果是否等于1即可。 代码&#xff1a; class Solution {public boolean isUg…

01_SQLite

文章目录 ** SQLite 存储各类和数据类型 **** SQLite 五种亲缘类型** SQLite 创建数据表删除数据表插入数据信息从数据表中获取数据&#xff0c;以结果表的形式返回数据&#xff08;结果集&#xff09;updatedistinctorder bygroup byhaving触发器删除一个触发器&#xff08;tr…

计网问答大题(期末复习)

计网总结笔记 概述 互联网的 2 个重要基本特点&#xff1a;连通性&#xff0c;资源共享 从互联网的工作方式上看&#xff0c;可以划分为两大块&#xff1a; •边缘部分&#xff1a; 由所有连接在互联网上的主机组成&#xff0c;由用户直接使用&#xff0c;用来进行通信&…

并查集【数据结构与算法】【C语言版-笔记】

目录 一、需求分析二、并查集三、代码实现3.1 Find函数3.2 Union函数3.3 优化13.4 终极优化2---压缩策略 一、需求分析 假设有n个互不相交的集合 ◼问题1&#xff1a;给定某个集合中的一个元素&#xff0c;查找该元素属于哪个集合&#xff1f; ◼问题2&#xff1a;如何合并两个…

建筑业挂靠行为的防范建议

在建筑行业中&#xff0c;挂靠行为的普遍存在给许多企业带来了法律风险和信誉风险。为了防范这些风险&#xff0c;企业需要采取一系列有效的措施。 一、加强资质管理 企业应当通过合法途径获取和提升自身的资质等级&#xff0c;避免因资质不足而产生挂靠的需求。加强资质管理是…

【半导体物理基础】第1章 半导体中的电子状态和能带,晶格结构,有效质量

目录 1.1 半导体晶格结构和结合性质 固体的种类 典型晶体 元素半导体 几种晶胞结构 晶向指数与晶面 半导体的晶体结构 金刚石结构 金刚石结构的结晶学原胞 硅、锗相关参数 硅、锗相关参数计算 闪锌矿结构 纤锌矿结构 氯化钠型结构 1.2 半导体中的电子状态和能带…

Study-Oracle-10-ORALCE19C-RAC集群搭建

一路走来,所有遇到的人,帮助过我的、伤害过我的都是朋友,没有一个是敌人。 ORACLE --RAC 搭建理念:准备工作要仔细,每个参数及配置都到仔细核对。环境准备完成后,剩下的就是图像化操作,没啥难度,所以图形化操作偷懒不续写了。 一、硬件信息及配套软件 1、硬件设置 RAC…

客厅落地台灯怎么摆放?五款客厅落地台灯款式分享

客厅落地台灯怎么摆放&#xff1f;客厅落地台灯是提升光线环境在室内光线质量的关键设备。但如果不慎购买到低质量的客厅落地台灯&#xff0c;可能会导致光线效果不佳&#xff0c;进而影响视力健康。因此&#xff0c;挑选一个可靠的品牌至关重要。那么&#xff0c;客厅落地台灯…

ubuntu 18.04 cuda 11.01 gpgpu-sim 裸机编译

1&#xff0c;环境 ubuntu 18.04 x86_64 cuda 11.01 gpgpu-sim master commit 90ec3399763d7c8512cfe7dc193473086c38ca38 2&#xff0c;预备环境 一个比较新的 ubuntu 18.04&#xff0c;为了迎合 cuda 11.01 的版本需求 安装如下软件&#xff1a; sudo apt-get instal…

Thinkphp/Laravel基于vue的的出版社书籍阅读管理系统

目录 技术栈和环境说明具体实现截图设计思路关键技术课题的重点和难点&#xff1a;框架介绍数据访问方式PHP核心代码部分展示代码目录结构解析系统测试详细视频演示源码获取 技术栈和环境说明 采用PHP语言开发&#xff0c;开发环境为phpstudy 开发工具notepad并使用MYSQL数据库…

netty之NettyClient半包粘包处理、编码解码处理、收发数据方式

前言 Netty开发中&#xff0c;客户端与服务端需要保持同样的&#xff1b;半包粘包处理&#xff0c;编码解码处理、收发数据方式&#xff0c;这样才能保证数据通信正常。在前面NettyServer的章节中我们也同样处理了&#xff1b;半包粘包、编码解码等&#xff0c;为此在本章节我们…

Pikichu-xss实验案例-通过xss获取cookie

原理图&#xff1a; pikachu提供了一个pkxss后台&#xff1b; 该后台可以把获得的cookie信息显示出来&#xff1b; 查看后端代码cookie.php&#xff1a;就是获取cookie信息&#xff0c;保存起来&#xff0c;然后重定向跳转到目标页面&#xff1b;修改最后从定向的ip&#xff0…

PTH 实验

1. 实验网络拓扑 kali: 192.168.72.128win2008: 192.168.135.129 192.168.72.139win7: 192.168.72.149win2012:(DC) 192.168.72.131 2. EXPLOIT 0x0. NTLM hash计算脚本 python3 -c import hashlib,binascii; print (binascii.hexlify(hashlib.new("md4", "…

基于51单片机的3路电压测量-proteus仿真

地址&#xff1a;https://pan.baidu.com/s/1PG2vzudc1QKHGSBfjPF0eQ 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectron…