9.2 Go语言入门(包和导入)

Go语言入门(包和导入)

  • 目录
    • 一、包和导入
      • 1. 包(Package)
        • 1.1 包的定义
        • 1.2 包的作用
        • 1.3 main 包
        • 1.4 非 main 包
      • 2. 导入(Import)
        • 2.1 导入标准库
        • 2.2 导入第三方包
        • 2.3 导入本地包
        • 2.4 导入别名
        • 2.5 导入并调用初始化函数
      • 3. 包的初始化顺序
      • 4. 循环导入
      • 5. 包的可见性

目录

Go 语言(Golang)是一种静态类型、编译型语言,由 Google 开发,专注于简洁性、并发和高效性。

下面是 Go 语言的基础语法讲解和代码示例。


上一篇:Go语言入门(环境篇)


一、包和导入

在 Go 语言中,包(package)和导入(import)机制是其模块化设计的核心。这些机制允许代码组织、重用和管理依赖性。下面详细讲解包和导入的概念、使用方法及相关细节。

1. 包(Package)

1.1 包的定义

在 Go 中,每个源文件都必须属于一个包。包的声明使用 package 关键字,通常放在文件的第一行。包名决定了该文件所属的包。

package main

1.2 包的作用

包用于将相关的代码组织在一起,提供命名空间来避免命名冲突。标准库和第三方库都是以包的形式存在。

1.3 main 包

main 包是特殊的包,它定义了一个可独立运行的可执行程序。只有包含 main 函数的 main 包才能被编译为可执行文件。

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

1.4 非 main 包

其他包(非 main 包)通常用于组织库代码,可以被其他包导入和使用。

package mathutils

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

2. 导入(Import)

2.1 导入标准库

标准库是 Go 自带的一组包,可以直接导入和使用。例如,fmt 包用于格式化 I/O。

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, World!")
}

2.2 导入第三方包

使用 go get 工具从远程仓库获取第三方包。例如:

go get github.com/gin-gonic/gin

然后在代码中导入:

package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run()
}

2.3 导入本地包

本地包可以使用相对或绝对路径导入。在项目目录下,结构可能如下:

project/
├── main.go
└── mathutils/
  └── add.go

main.go 文件导入 mathutils 包:

package main

import (
    "fmt"
    "project/mathutils"
)

func main() {
    result := mathutils.Add(1, 2)
    fmt.Println(result)
}

2.4 导入别名

导入包时可以使用别名,这在包名过长或包名冲突时特别有用。

package main

import (
    f "fmt"
)

func main() {
    f.Println("Hello, World!")
}

2.5 导入并调用初始化函数

如果只想导入包并调用其初始化函数而不使用其中的任何导出函数,可以使用空白标识符 _

package main

import (
    _ "net/http/pprof"
)

func main() {
    // pprof 的初始化函数会被调用,但我们不使用其任何导出函数
}

3. 包的初始化顺序

每个包都可以包含一个 init 函数,用于包的初始化逻辑。在导入时,init 函数会在包的所有其他函数之前执行。如果一个包被多次导入,init 函数只会执行一次。


  1. 在 Go 语言中,每个包都可以包含一个名为 init 的函数,用于执行包的初始化逻辑。这个 init 函数在包被导入时会自动执行,而不需要手动调用。它的作用是在包被使用之前执行一些必要的初始化工作。

  2. 当导入一个包时,其中的 init 函数会在包的所有其他函数之前被执行。这意味着在使用包中的其他函数之前,包的初始化工作会首先完成。

  3. 如果同一个包被多次导入,其中的 init 函数只会执行一次。这是因为 init 函数在整个程序生命周期内只会被执行一次,即使导入它的包被多次引用也不会重复执行。这确保了包的初始化逻辑只会执行一次,避免了重复的初始化工作和可能的副作用。


总的来说,init 函数是用于包的初始化的特殊函数,它在导入时自动执行,负责包的初始化工作,并且只会执行一次,即使包被多次导入也不会重复执行。

下面是一个简单的示例来演示这个行为:
假设有一个名为 example 的包,其中包含一个 init 函数:

// example.go
package example

import "fmt"

func init() {
    fmt.Println("Initializing example package")
}


然后,我们在另一个文件中多次导入 example 包:

// main.go
package main

import (
    "example"
    "example"
)

func main() {
    fmt.Println("Main function")
}

当执行 main.go 文件时,我们可以看到 example 包的 init 函数只会被执行一次,即使该包被多次导入。

输出结果:

Initializing example package
Main function

4. 循环导入

Go 不允许包之间存在循环导入依赖。例如,包 A 导入包 B,包 B 又导入包 A,这会导致编译错误。解决循环导入问题的方法包括重构代码、使用接口或将共有逻辑提取到第三个包中。

循环导入问题通常是由于包之间的相互依赖关系不正确引起的。下面是一个简单的示例来模拟循环导入问题以及解决方法:
假设有两个包 A 和 B,它们互相导入并且存在循环依赖:

// a.go
package a

import "b"

func AFunc() {
    b.BFunc()
}

// b.go
package b

import "a"

func BFunc() {
    a.AFunc()
}

在这种情况下,当尝试编译时会出现循环导入错误。
解决循环导入问题的方法之一是重构代码,将共享的逻辑提取到第三个包中。例如,我们可以创建一个新的包 common,将两个包的共享逻辑移动到其中:

// common.go
package common

func CommonFunc() {
    // 共享逻辑
}

然后,包 A 和包 B 分别导入 common 包并使用其中的逻辑:

// a.go
package a

import "common"

func AFunc() {
    common.CommonFunc()
}

// b.go
package b

import "common"

func BFunc() {
    common.CommonFunc()
}

通过这种方式,我们消除了循环导入问题,并且可以在不同的包之间共享逻辑。

5. 包的可见性

在 Go 中,包内标识符的首字母大小写决定了其可见性。首字母大写的标识符是导出的,可以被其他包访问;首字母小写的标识符是包内私有的,不能被其他包访问。

package mypackage

// 导出函数
func PublicFunc() {
    // ...
}

// 私有函数
func privateFunc() {
    // ...
}

总结
Go 的包和导入机制提供了强大的模块化支持,帮助开发者组织代码和管理依赖性。通过合理使用包,可以提高代码的可维护性和可重用性。理解包的定义、导入方法、初始化顺序和可见性规则,是掌握 Go 语言的重要一步。


下一篇:二、Go语言入门(变量声明和函数调用)


在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/642228.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】整型提升与char取值范围

整型提升介绍 C语言中整型算术运算总是至少以缺省(默认)整型类型的精度来进行的。为了获得这个精度,表达式中字符、短整型操作数在使用前被转换为普通整型。而这个过程是悄悄发生的。 整型提升的意义: 表达式的整型运算要在CPU…

二叉树—先后序线索化和先后序线索遍历

有了上篇文章的基础,先序和后序的线索化逻辑一样。 代码如下: void preOrderThreadTree(TreeNode* T,TreeNode** pre) {if (T NULL) {;}else {//printf("%c ", T->val);if (T->lchild NULL) {T->ltag 1;T->lchild *pre;}if …

逻辑这回事(一)----编码规范

说明:优先级是M的规则为强制项,优先级为R的规则为建议项。 通用约束 应有全局观念。 优先级:M 说明:你所编写的代码在成为最终硅片上的一部分之前,需要经过许多设计者利用各种各样的工具进行各种各样的处理。有时&…

【知识拓展】ngrok-高性价比的内网穿透工具

前言 使用google colab运行的web应用无法打开进行测试。 第一时间想到是否有相关工具能将内网映射到外网供访问。于是找到了ngrok。 ngrok 是什么,我们为什么要使用它? ngrok官网是一个全球分布的反向代理,无论您在哪里运行,它…

VUE3和VUE2

VUE3和VUE2 上一篇文章中,我们对VUE3进行了一个初步的认识了解,本篇文章我们来进一步学习一下,顺便看一下VUE2的写法VUE3是否能做到兼容😀。 一、新建组件 我们在components中新建一个组件,名称为Peron,…

yolov10 快速使用及训练

参考: https://docs.ultralytics.com/models/yolov10/ ultralytics其实大多数系列都能加载使用: 官方: https://github.com/THU-MIG/yolov10.git 代码参考: https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/train-yolov10-object-…

无人机的相关基础知识(看不懂了 待定以后继续补充)

视频: 【浙江大学】浙大博导带你从0制作无人机_哔哩哔哩_bilibili 什么是无人飞行器 无人机自主导航构架 IMU(加速度计和陀螺仪),可以测出当前的 加速度和角速度 这俩信息再去融合外部传感器 (例如视觉传感器或者雷…

【全网最全】2024电工杯数学建模A题成品论文+前三题完整解答matlab+py代码等(后续会更新成品论文)

您的点赞收藏是我继续更新的最大动力! 一定要点击如下的卡片链接,那是获取资料的入口! 【全网最全】2024电工杯数学建模A题成品论文前三题完整解答matlabpy代码等(后续会更新成品论文)「首先来看看目前已有的资料&am…

水表电表远程抄表是什么?

1.简述:水表电表远程抄表技术性 随着时代的发展,传统式手动抄表方法早已被更为高效、智能化的远程抄表系统所替代。水表电表远程抄表,说白了,就是利用互联网技术完成对水表和电表读数的远程数据采集管理方法,大大提升…

【移动云】5G时代——你我的智慧云

文章目录 0.引言1.移动云简介2.移动云学习资源3.移动云产品介绍3.1 大数据—数据可视化(DataInsight)3.1.1 应用场景3.1.2 产品基本架构3.1.3 优势 3.2 云主机ECS3.2.1 云主机ECS优势3.2.2 云主机主要功能3.2.3 应用场景 4.移动云解决方案4.1 热门案例1&…

BUUCTF靶场[Web] [极客大挑战 2019]Havefun1、[HCTF 2018]WarmUp1、[ACTF2020 新生赛]Include

[web][极客大挑战 2019]Havefun1 考点:前端、GET传参 点开网址,发现是这个界面 点击界面没有回显,老规矩查看源代码,看到以下代码 代码主要意思为: 用get传参,将所传的参数给cat,如果catdog…

浅谈面向对象--知识补充

This关键字 this 内存图 this关键字表示当前对象本身,一般用于类的内部,其内部存在一个地址,指向当前初始化的对象本身。 当new一个对象时,实际上产生了两个引用,一个是供类Dog内部调用其成员变量和成员方法的this关键…

用HAL库改写江科大的stm32入门例子-6-2 定时器外部时钟

实验目的: 熟悉外部时钟的应用。 实验步骤: 创建项目参照前面的文章,集成oled(没有oled,用uart串口传递也可以)选择外部时钟源时钟源参数设置编写代码: 5.1声明全局变量,如果发生定时器中断的时候,在回调…

Python条件分支与循环

大家好,当涉及到编写高效和灵活的程序时,条件分支和循环是 Python 中至关重要的概念。它们允许我们根据不同的条件执行不同的代码块,或者重复执行一组语句。条件分支和循环是测试开发工程师在日常工作中经常使用的工具,无论是编写…

Elasticsearch集群搭建学习

Elasticsearch集群聚合、集群搭建 RestClient查询所有高亮算分控制 数据聚合DSL实现Bucket聚合DSL实现Metrics聚合RestAPI实现聚合 拼音分词器如何使用拼音分词器?如何自定义分词器?拼音分词器注意事项? 自动补全数据同步集群搭建ES集群结构创…

护眼小贴士:学生如何正确使用台灯?

随着电子设备的普及和长时间的用眼,长时间盯着屏幕或学习,眼睛需要不断调节焦距,导致眼睛肌肉疲劳,进而引发视力下降。这种现象在年轻一代甚至青少年中尤为普遍,这种疲劳状态不仅影响眼睛的舒适度,还会导致…

springboot打包目录解析

一、引言 Java开发中我们使用最多的便是spring框架,比如springboot应用。微服务模式下,每个服务都是一个springboot应用,都会被打包成一个可执行jar包。那么我们有多少人尝试去了解过这个可执行jar到底是什么?它的结构是什么样的…

[保姆式教程]使用目标检测模型YOLO V8 OBB进行旋转目标的检测:训练自己的数据集(基于卫星和无人机的农业大棚数据集)

最近需要做基于卫星和无人机的农业大棚的旋转目标检测,基于YOLO V8 OBB的原因是因为尝试的第二个模型就是YOLO V8,后面会基于YOLO V9模型做农业大棚的旋转目标检测。YOLO V9目前还不能进行旋转目标的检测,需要修改代码 PS:欢迎大家分享农业大…

深入解析:如何高效地更新Python字典

新书上架~👇全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一、引言 二、修改字典中的值 三、向字典中添加键值对 四、更新字典的两种方法总结 五、…