Go模块管理踩坑实录:从入门到放弃再到真香

大家好,我是老墨。 很早之前,翻译了一篇 Golang 官方的模块管理文档中文,那篇有点“官方”了,今天老墨搞一篇接地气的模块实战教程。 说实话,我第一次接触 Go 模块的时候,内心是拒绝的。 GOPATH 那套虽然老,但好歹能用。突然冒出来个 go.mod、go.sum,还有什么 replace、indirect,看着就头大。更别提那些看起来像乱码的版本号:v1.2.3-0.20210101000000-abcdef123456,这是什么鬼? 但折腾了几个月后,我发现:真香。 今天就把我踩过的坑、学到的经验,全部掏出来。不讲理论,只讲实战。 为什么要用Go模块? 先说说为什么要用模块,而不是继续用GOPATH。 GOPATH 的三大痛点 版本管理是灾难 所有依赖都在 $GOPATH/src 下 同一个包只能有一个版本 项目 A 用 v1.0,项目 B 用 v2.0?抱歉,做不到 依赖地狱 依赖的依赖的依赖……谁也不知道用了什么版本 换台机器编译?祝你好运 团队协作?每个人的依赖都不一样 无法复现构建 今天能编译,明天就不行了 因为依赖包更新了 你根本不知道 Go 模块解决了什么 每个项目独立管理依赖 版本号明确,可复现构建 依赖关系清晰,记录在 go.mod 校验和保证安全性(go.sum) 支持私有仓库和代理 快速上手:5分钟创建第一个模块 1. 初始化模块 1# 创建项目目录 2mkdir myproject 3cd myproject 4 5# 初始化模块 6go mod init github.com/yourusername/myproject 这会生成一个go.mod文件: 1module github.com/yourusername/myproject 2 3go 1.21 就这么简单。 2. 添加依赖 写点代码,导入个包: ...

2026-02-25 · 4 min · 751 words · 老墨

Python教程20:模块基础

Python教程20:模块基础 “分而治之,事半功倍。” 当代码越来越多时,把所有代码放在一个文件里会变得难以维护。模块(Module)就是Python的代码组织方式,让你可以把相关功能分门别类。今天我们学习如何创建和使用模块。 1. 什么是模块 定义 **模块(Module)**是一个包含Python代码的.py文件。每个Python文件都可以作为一个模块被其他文件导入使用。 为什么需要模块: 代码复用:写一次,到处用 命名空间:避免变量名冲突 代码组织:按功能分类,便于维护 协作开发:不同人负责不同模块 简单示例 创建一个文件math_utils.py: 1# math_utils.py 2"""数学工具模块""" 3 4PI = 3.14159 5 6def add(a, b): 7 """加法""" 8 return a + b 9 10def circle_area(radius): 11 """计算圆面积""" 12 return PI * radius ** 2 13 14class Calculator: 15 """计算器类""" 16 def multiply(self, a, b): 17 return a * b 在另一个文件中使用: 1# main.py 2import math_utils # 导入模块 3 4print(math_utils.PI) # 3.14159 5print(math_utils.add(3, 5)) # 8 6print(math_utils.circle_area(5)) # 78.53975 7 8calc = math_utils.Calculator() 9print(calc.multiply(4, 5)) # 20 模块的本质: 模块是一个命名空间(namespace) 文件名(去掉.py)就是模块名 通过模块名访问其中的变量、函数、类 2. 导入模块的方式 Python提供了多种导入方式,适应不同场景。 方式1:import模块名 1import math_utils 2 3# 使用:模块名.成员 4result = math_utils.add(1, 2) 优点: ...

2024-09-06 · 3 min · 554 words · 老墨

(译)Go1.13中处理错误

本文翻译自GoLang官方文档, 见原文地址. 介绍 在过去的十年中,Go 将 “错误作为值” 来处理 ,这对我们很有帮助。尽管标准库对错误的支持很少 —— 只有 errors.New 和 fmt.Errorf 函数,它们产生的错误只包含一条消息 —— 内置 error 接口允许 Go 程序员添加他们想要的任何信息。它所需要的只是一个实现 Error 方法的类型: 1type QueryError struct { 2 Query string 3 Err error 4} 5 6func (e *QueryError) Error() string { return e.Query + ": " + e.Err.Error() } 像这样的错误类型无处不在,它们存储的信息千差万别,从时间戳到文件名再到服务器地址。通常,该信息包括另一个较低级别的错误以提供额外的上下文。 一个错误包含另一个错误的模式在 Go 代码中非常普遍,经过 广泛讨论 后,Go 1.13 添加了对它的明确支持。这篇文章描述了提供该支持的标准库的新增内容:errors 包中的三个新函数,以及 fmt.Errorf. 在详细描述更改之前,让我们回顾一下在该语言的先前版本中如何检查和构造错误。 Go 1.13 之前的错误 检查错误 Go 错误是值。程序以几种方式根据这些值做出决策。最常见的是比较错误以 nil 查 看操作是否失败。 1if err != nil { 2 // something went wrong 3} 有时我们将错误与已知的 标记 值进行比较,以查看是否发生了特定错误。 ...

2023-05-05 · 4 min · 743 words · 老墨

(译)Go错误是值

Rob Pike,2015 年 1 月 12 日 ,原文地址: https://go.dev/blog/errors-are-values Go 程序员(尤其是刚接触该语言的程序员)讨论的一个共同点是如何处理错误,这些讨论最终往往都将回归于无数次出现的代码片段: 1if err != nil { 2 return err 3} 如上所示,但我们最近扫描了所有我们能找到的开源项目,发现这个片段每页或每两页只出现一次,比某些人认为的要少。尽管如此,许多程序员仍然认为必须键入如下代码来处理错误: 1if err != nil 一直以来,人们觉得一定有什么地方出了问题,而明显的目标就是 Go 本身。 这是不幸的、误导性的,而且很容易纠正。也许刚接触 Go 的程序员会问,“我该如何处理错误?”,然后学习这种模式,最后就此打住。在其他语言中,可能会使用 try-catch 块或其他类似机制来处理错误。因此,程序员认为,我在我的旧语言中可以使用 try-catch 时,但在 go 中我只能输入 if err != nil 来处理错误。随着时间的推移,Go 代码收集了许多这样的片段,结果感觉很笨拙。 不管这种解释是否成立,很明显这些 Go 程序员忽略了关于错误的一个基本观点: 错误是值。 可以对值进行编程,并且由于错误是值,因此可以对错误进行编程。 当然,涉及错误值的常见语句是测试它是否为 nil,但是错误值可以做无数其他事情,应用其中一些其他事情可以使您的程序更好,从而消除大部分样板代码,避免多次使用 if 语句检查每个错误。 一个简单示例是 bufio 包中的 https://go.dev/pkg/bufio/#Scanner[`Scanner`]。它的 https://go.dev/pkg/bufio/#Scanner.Scan[`Scan`] 方法执行底层 I/O,这当然可能导致错误。然而,该 Scan 方法根本不会暴露错误。相反,它返回一个布尔值和一个单独的方法,在扫描结束时运行,报告是否发生错误。客户端代码如下所示: 1scanner := bufio.NewScanner(input) 2for scanner.Scan() { 3 token := scanner.Text() 4 // process token 5} 6if err := scanner.Err(); err != nil { 7 // process the error 8} 当然,有一个 nil 检查错误,但它只出现并执行一次。假设将该 Scan 方法改为: ...

2023-04-30 · 2 min · 389 words · 老墨

(译)Go模块:管理依赖项

文章翻译自Golang官方文档,见原文地址。 当您的代码使用外部包时,这些包(作为模块分发)成为依赖项。随着时间的推移,您可能需要升级或更换它们。Go 提供了依赖管理工具,可帮助您在合并外部依赖项时确保 Go 应用程序的安全。 本文介绍如何执行一些任务来管理您代码中的依赖项,您可以使用 Go tools 执行其中的大部分操作。本主题还介绍了如何执行其他一些您可能会觉得有用的依赖相关任务。 相关阅读: 如果您不熟悉模块和依赖,请查看 入门教程 以获得简要介绍。 使用该 go 命令管理依赖项有助于确保您的需求保持一致,并且您的 go.mod 文件的内容是有效的。有关命令的参考,请参阅 go命令文档。您还可以通过键入 go help 命令名称从命令行获取帮助,如go help mod tidy`. 使用 Go 命令更改依赖项时会编辑 go.mod 文件。有关文件内容的更多信息,请参阅 go.mod 文件参考文档。 让您的编辑器或 IDE 能够感知 Go 模块可以让您更轻松地管理它们。有关支持 Go 的编辑器的更多信息,请参阅 编辑器插件和 IDE。 本主题不描述如何开发、发布和版本模块以供其他人使用。有关更多信息,请参阅 开发和发布模块。 使用和管理依赖项的工作流程 您可以通过 Go tools 获取和使用有用的包。在 pkg.go.dev 上,您可以搜索您觉得有用的包,然后使用 go 命令将这些包导入您自己的代码中以调用它们的功能。 下面列出了最常见的依赖管理步骤: 在 pkg.go.dev 上 «查找和导入包, 查找有用的包»。 «查找和导入包, 在代码中导入所需的包»。 将您的代码添加到模块以进行依赖跟踪(如果它不在模块中)。请参阅 «代码中启用依赖项跟踪, 启用依赖项跟踪» [«添加依赖项, 添加外部包作为依赖项»,以便您可以管理它们。 随着时间的推移,根据需要 «升级或降级依赖项, 升级或降级依赖版本»。 依赖项作为模块管理 在 Go 中,依赖项作为包含导入包的模块来管理。此过程由以下功能支持: ...

2023-04-19 · 3 min · 628 words · 老墨