当前位置:首页 > 文章列表 > Golang > Go教程 > 详解Go语言中关于包导入必学的 8 个知识点

详解Go语言中关于包导入必学的 8 个知识点

来源:脚本之家 2022-12-30 17:57:32 0浏览 收藏

在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《详解Go语言中关于包导入必学的 8 个知识点》,聊聊语言包导入,希望可以帮助到正在努力赚钱的你。

1. 单行导入与多行导入

在 Go 语言中,一个包可包含多个 .go 文件(这些文件必须得在同一级文件夹中),只要这些 .go 文件的头部都使用 package 关键字声明了同一个包。

导入包主要可分为两种方式:

单行导入

import "fmt"
import "sync" 

多行导入

import(
  "fmt"
  "sync"
)

如你所见,Go 语言中 导入的包,必须得用双引号包含,在这里吐槽一下。

2. 使用别名

在一些场景下,我们可能需要对导入的包进行重新命名,比如

我们导入了两个具有同一包名的包时产生冲突,此时这里为其中一个包定义别名

import (
  "crypto/rand"
  mrand "math/rand" // 将名称替换为mrand避免冲突
)

我们导入了一个名字很长的包,为了避免后面都写这么长串的包名,可以这样定义别名

import hw "helloworldtestmodule"

防止导入的包名和本地的变量发生冲突,比如 path 这个很常用的变量名和导入的标准包冲突。

import pathpkg "path"

3. 使用点操作

如里在我们程序内部里频繁使用了一个工具包,比如 fmt,那每次使用它的打印函数打印时,都要 包名+方法名。

对于这种使用高频的包,可以在导入的时,就把它定义会 "自己人"(方法是使用一个 . ),自己人的话,不分彼此,它的方法,就是我们的方法。

从此,我们打印再也不用加 fmt 了。

import . "fmt"

func main() {
  Println("hello, world")
}

但这种用法,会有一定的隐患,就是导入的包里可能有函数,会和我们自己的函数发生冲突。

4. 包的初始化

每个包都允许有一个 init 函数,当这个包被导入时,会执行该包的这个 init 函数,做一些初始化任务。

对于 init 函数的执行有两点需要注意

init 函数优先于 main 函数执行

在一个包引用链中,包的初始化是深度优先的。比如,有这样一个包引用关系:main→A→B→C,那么初始化顺序为

C.init→B.init→A.init→main

5. 包的匿名导入

当我们导入一个包时,如果这个包没有被使用到,在编译时,是会报错的。

但是有些情况下,我们导入一个包,只想执行包里的 init 函数,来运行一些初始化任务,此时怎么办呢?

可以使用匿名导入,用法如下,其中下划线为空白标识符,并不能被访问

// 注册一个PNG decoder
import _ "image/png"

由于导入时,会执行 init 函数,所以编译时,仍然会将这个包编译到可执行文件中。

6. 导入的是路径还是包?

当我们使用 import 导入 testmodule/foo 时,初学者,经常会问,这个 foo 到底是一个包呢,还是只是包所在目录名?

import "testmodule/foo"

为了得出这个结论,专门做了个试验(请看「第七点里的代码示例」),最后得出的结论是:

导入时,是按照目录导入。导入目录后,可以使用这个目录下的所有包。

出于习惯,包名和目录名通常会设置成一样,所以会让你有一种你导入的是包的错觉。

7. 相对导入和绝对导入

据我了解在 Go 1.10 之前,好像是不支持相对导入的,在 Go 1.10 之后才可以。

绝对导入:从 $GOPATH/src$GOROOT 或者 $GOPATH/pkg/mod 目录下搜索包并导入

相对导入:从当前目录中搜索包并开始导入。就像下面这样

import (
  "./module1"
  "../module2"
  "../../module3"
  "../module4/module5"
)

分别举个例子吧

一、使用绝对导入

有如下这样的目录结构(注意确保当前目录在 GOPATH 下)

其中 main.go 是这样的

package main

import (
  "app/utilset"  // 这种使用的就是绝对路径导入
)

func main() {
  utils.PrintHello()
}

而在 main.go 的同级目录下,还有另外一个文件夹 utilset ,为了让你理解 「第六点:import 导入的是路径而不是包」,我在 utilset 目录下定义了一个 hello.go 文件,这个go文件定义所属包为 utils

package utils

import "fmt"

func PrintHello(){
  fmt.Println("Hello, 我在 utilset 目录下的 utils 包里")
}

运行结果如下

二、使用相对导入

还是上面的代码,将绝对导入改为相对导入后

将 GOPATH 路径设置回去(请对比上面使用绝对路径的 GOPATH)

然后再次运行

总结一下,使用相对导入,有两点需要注意

项目不要放在 $GOPATH/src 下,否则会报错(比如我修改当前项目目录为GOPATH后,运行就会报错)

Go Modules 不支持相对导入,在你开启 GO111MODULE 后,无法使用相对导入。

最后,不得不说的是:使用相对导入的方式,项目可读性会大打折扣,不利用开发者理清整个引用关系。

所以一般更推荐使用绝对引用的方式。使用绝对引用的话,又要谈及优先级了

8. 包导入路径优先级

前面一节,介绍了三种不同的包依赖管理方案,不同的管理模式,存放包的路径可能都不一样,有的可以将包放在 GOPATH 下,有的可以将包放在 vendor 下,还有些包是内置包放在 GOROOT 下。

那么问题就来了,如果在这三个不同的路径下,有一个相同包名但是版本不同的包,我们导入的时候,是选择哪个进行导入呢?

这就需要我们搞懂,在 Golang 中包搜索路径优先级是怎样的?

这时候就需要区分,是使用哪种模式进行包的管理的。

如果使用 govendor

当我们导入一个包时,它会:

  • 先从项目根目录的 vendor 目录中查找
  • 最后从 $GOROOT/src 目录下查找
  • 然后从 $GOPATH/src 目录下查找
  • 都找不到的话,就报错。

为了验证这个过程,我在创建中创建一个 vendor 目录后,就开启了 vendor 模式了,我在 main.go 中随便导入一个包 pkg,由于这个包是我随便指定的,当然会找不到,找不到就会报错, Golang 会在报错信息中打印中搜索的过程,从这个信息中,就可以看到 Golang 的包查找优先级了。

如果使用 go modules

你导入的包如果有域名,都会先在 $GOPATH/pkg/mod 下查找,找不到就连网去该网站上寻找,找不到或者找到的不是一个包,则报错。

而如果你导入的包没有域名(比如 "fmt"这种),就只会到 $GOROOT 里查找。

还有一点很重要,当你的项目下有 vendor 目录时,不管你的包有没有域名,都只会在 vendor 目录中想找。

通常vendor 目录是通过 go mod vendor 命令生成的,这个命令会将项目依赖全部打包到你的项目目录下的 verdor 文件夹中。

延伸阅读如何使用go module导入本地包

本篇关于《详解Go语言中关于包导入必学的 8 个知识点》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于Golang的相关知识,请关注golang学习网公众号!

版本声明
本文转载于:脚本之家 如有侵犯,请联系study_golang@163.com删除
Golang 变量申明的三种方式Golang 变量申明的三种方式
上一篇
Golang 变量申明的三种方式
golang 进度条功能实现示例
下一篇
golang 进度条功能实现示例
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 笔灵AI生成答辩PPT:高效制作学术与职场PPT的利器
    笔灵AI生成答辩PPT
    探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
    14次使用
  • 知网AIGC检测服务系统:精准识别学术文本中的AI生成内容
    知网AIGC检测服务系统
    知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
    22次使用
  • AIGC检测服务:AIbiye助力确保论文原创性
    AIGC检测-Aibiye
    AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
    30次使用
  • 易笔AI论文平台:快速生成高质量学术论文的利器
    易笔AI论文
    易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
    40次使用
  • 笔启AI论文写作平台:多类型论文生成与多语言支持
    笔启AI论文写作平台
    笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
    35次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码