当前位置: 首页 > article >正文

02 go语言(golang) - 包和模块

包(package)

在Go语言中,包(package)是一种封装代码的方式,用于组织和重用代码。包可以被看作是一个功能模块,它可以包含函数、变量、类型(如结构体和接口)以及其他包。使用包可以帮助开发者管理大型项目的复杂性,并促进代码的模块化和可维护性。

包的基本概念

  1. 定义

    • 每个Go文件都属于一个包,且文件中的第一行非注释代码应声明该文件所属的包。
    • 例如:package main 表示该文件属于 main 包。
  2. 导入

    • 如果你想使用其他包中定义的公共标识符(如函数、类型等),需要先导入这个包。
    • 使用 import 语句来导入需要的包。

    例如:import "fmt" 导入标准库中的 fmt

    // 导入一个包
    import "awesomeProject/test"
    
    // 导入多个包
    import "awesomeProject/test"
    import "fmt"
    
    // 导入多个包
    import (
    	"awesomeProject/test"
    	"fmt"
    )
    
  3. 主程序入口

    • Go程序由一个名为 main 的特殊包开始执行,这个名为 main() 的函数是每个可执行程序必需的起点。
    • 只有名为 main 的包可以编译成一个可执行文件。
  4. 路径

    • 导入语句中使用字符串指定要导入的包路径。这些路径相对于 $GOPATH/src 或者 Go模块内部目录结构来解析。
  5. 初始化顺序

    • 包级变量按声明顺序初始化。
    • 每个包可以有一个或多个init函数,这些函数在所有变量声明后自动调用,并且在任何其他代码运行之前完成设置。
  6. 可见性:

    • 在Go中,默认情况下,在同一软件内部所有处都能访问同一软件内部不同源码文件里定义并且首字母大写命名规则命名过后标识符(如类型、变量、常数或者函数)。如果首字母小写,则表示它仅对同一软件内部相同源码所在目录下其它源码而言是私有(private)属性或方法。

示例

假设我们有几个测试文件,结构目录:

awesomeProject/
├── go.mod
├── main.go
└── _01package/
    └── one.go
    └── two.go
└── _02package/
		└── three.go
  • one.go:
package main

import "awesomeProject/_02package"

func main() {
	println("one")

	// 注:包的导入是导入整个包(文件夹),而不是里面的文件,使用包名可以直接调用模块里面所有文件夹的函数

	// 同个包下,无需导入直接使用
	TwoFunc()
	twoFunc()

	// 不同包,需要导入
	_02package.ThreeFunc()
	// 小写的方法(函数)只在同个包内可见,不可在其他包中调用
	// _02package.threeFunc()

}

  • two.go:
package main

import "fmt"

func TwoFunc() {
	fmt.Println("two...")
}

func twoFunc() {
	fmt.Println("two...")
}

  • three.go
package _02package

func ThreeFunc() {
	println("three...")
}

func threeFunc() {
	println("three...")
}

报错:Multiple packages in the directory

在Go语言中,一个目录下的所有文件必须属于同一个包。这是Go的一项约定,它有助于简化构建过程和包管理。当你在同一个目录下拥有属于不同包的文件时,就会遇到你描述的问题:“Multiple packages in the directory”。

解决方案

  1. 统一包名
    • 确保该目录下所有文件的第一行声明的包名相同。
    • 例如,如果你希望所有文件都属于main包,则每个文件都应该以package main开始。
  2. 分离到不同目录
    • 如果这些文件确实应该属于不同的包,则应将它们移动到不同的目录中。
    • 每个目录可以有自己独立的包名,并且可以通过导入路径来引用其他目录(即其他包)中定义的公共标识符。

确保单个目录内只含有单一类型Package是关键。这样做既符合Go语言设计原则也能避免类似上述多Package错误提示。如果功能模块之间需要交互作用, 可以通过适当地组织代码并利用import机制来实现跨packages调用。

模块(module)

Go模块(Go Modules)是Go语言的官方依赖管理系统,自Go 1.11版本引入,并在Go 1.13中成为默认的依赖管理方式。模块系统旨在解决包的版本控制和依赖问题,使得源代码更易于维护、分享和协作开发。

核心概念

  1. 模块(Module)

    • 模块是相关Go包的集合。它是一个独立单元,拥有自己的go.mod文件,在这个文件中声明了模块路径和其依赖项。
    • 模块路径通常是版本控制仓库的位置,如 github.com/username/projectname
  2. go.mod 文件

    • 这个文件位于模块根目录下,标识了该目录内容属于哪个模块。

    • 它列出了项目所需的所有依赖项及其正确版本。

    • 示例内容:

      module github.com/username/myproject
      
      go 1.15
      
      require (
          github.com/some/dependency v1.2.3
          golang.org/x/text v0.3.2
      )
      
  3. go.sum 文件

    • 当运行像 go buildgo test 这样会自动更新 go.mod 的命令时,会同时生成或更新一个名为 go.sum 的文件。
    • 这个文件包含特定依赖项内容的预期加密哈希值,用以确保项目所使用的每个外部模块不被篡改或意外更改。
  4. 版本控制

    • Go Modules支持语义化版本号(Semantic Versioning),例如:v0.1, v1, v2等。
    • 可以指定使用特定版本、最新发布版或者某一分支上最新提交。
  5. 代理服务器(Proxy Server):

    • Go提供了一个公共代理服务器(https://proxy.golang.org),用来缓存公共可访问模块的所有公开发布版本。
    • 使用代理可以提高构建速度、提供无法直接访问某些VCS服务时候需要下载代码包时候备选方案。

通过引入Modules机制, Go语言大大简化了跨环境工作流程中对第三方库管理需求处理过程。这不仅使得开发者能够更容易地管理大型项目中复杂且多变动态性强烈需求场景下各种软件包之间相互关系与影响情况,并且也有助于确保软件构建过程稳定性与安全性。

模块(第三方依赖)的使用

1、使用专门的网站,查到你需要的依赖以及版本号

  • pkg.go.dev:这是Go官方提供的包文档和索引网站。你可以在这里搜索可用的包,并查看其文档、版本和许可信息。
  • GitHub 或其他代码托管平台:许多开源Go项目都托管在GitHub上。通过关键词搜索或浏览相关组织/用户的仓库,你可以找到所需库。

2、在go.mod中导入,比如我找的date这个依赖

require github.com/Azure/go-autorest/autorest/date v0.3.0

3、在项目目录下执行命令下载安装依赖

➜ awesomeProject go get github.com/Azure/go-autorest/autorest/date
go: downloading github.com/Azure/go-autorest v14.2.0+incompatible
go: downloading github.com/Azure/go-autorest/autorest v0.11.29
➜ awesomeProject 

4、在代码中导入依赖并使用

package main

import (
	"github.com/Azure/go-autorest/autorest/date"
)

func main() {
	d, _ := date.ParseDate("2024-10-01")
	print(d.String())
}

总结异同点

  1. 包(Package)

    • 包是 Go 语言中代码组织的基本单位。一个包可以包含多个.go源文件,这些文件中的代码共享相同的包名。
    • 包用于将功能相关的代码组织在一起,并且可以通过导入语句(import)被其他包使用。
    • 包提供了一种封装机制,允许开发者将内部实现细节隐藏起来,只暴露出一部分接口(即公开的函数、变量、类型等)。
  2. 模块(Module)

    • 从 Go 1.11 版本开始,Go 引入了模块作为依赖管理和封装的单位,这是对传统包概念的扩展。
    • 一个模块通常对应一个项目或库,它包含了一组相关的包。模块拥有自己的依赖关系,并且可以跨项目共享。
    • 模块定义了一组版本化的包,这些包可以被其他模块导入。模块通过 go.mod 文件来管理依赖关系,这个文件记录了模块的依赖和版本信息。
    • 模块的使用简化了依赖管理,使得开发者可以更容易地构建、测试和共享代码。

http://www.kler.cn/news/354631.html

相关文章:

  • 什么是 SQL 命令?SQL 如何工作?
  • Maven基于构建阶段分析多余的依赖
  • Linux 下find常用命令整理(更新ing)
  • HCIP-HarmonyOS Application Developer 习题(十二)
  • 阿加犀构建开发者生态的全链路赋能之旅
  • QGIS--DEMTO3D
  • Pytorch分布式训练杂记1
  • DS链式二叉树的基本操作和OJ题(12)
  • mysql数据同步ES方案---DTS
  • 鸿蒙开发 四十四 ArkTs BuilderParam传递UI(二)
  • 开发一个微信小程序要多少钱?
  • Selenium 中定位元素操作集合
  • 面试经典150题刷题记录
  • 代码随想录算法训练营Day28
  • electron-vite_6js-cookie失效
  • react+video:限制快进、倍速、画中画
  • el-table中实现可选表格区域的鼠标事件检测
  • 程序员35+出路何在?
  • 三格电子-Profibus-DP转光纤点对点式【MS-F155-P】
  • springboot+react实现移动端相册(上传图片到oss/ 批量删除/ 查看图片详情等功能)