【Go 编程实践】从零到一:创建、测试并发布自己的 Go 库
为什么需要开发自己的 Go 库
在编程语言中,包(Package)和库(Library)是代码组织和复用的重要工具。在 Go 中,包是代码的基本组织单位,每个 Go 程序都由包构成。包的作用是帮助组织代码,提供封装和代码复用的机制。
Go 包可以包含函数、类型、变量和常量等,这些元素可以被其他包引用和使用。例如,Go 的标准库提供了大量的包,如 net/http 包提供了 HTTP 客户端和服务器实现,fmt 包提供了格式化、I/O 函数等。
而库是一种特殊的包,不包含 main 函数,不能被直接运行,但可以被其他程序引用。库通常包含一些常用的功能或算法,如字符串处理、数学计算、网络通信等。
开发自己的 Go 库的优点:
- 复用性:当在多个项目中需要使用相同的功能时,可以将这些功能封装在一个库中,然后在需要的地方引用他。这样可以避免重复编写相同的代码,提高编程效率。
- 可维护性:当需要修改某个功能时,只需修改对应的库,而不需要在多个地方进行修改,这样可以使代码更易于理解和维护。
- 可测试性:为每个库编写单元测试,确保他们的功能正确。修改代码时,可以运行这些测试来检查是否引入了新的错误。
接下来,将以 Asiatz(github.com/mazeyqian/asiatz)为例,详细演示如何创建一个规范的 Go 库。
Asiatz 主要功能是进行时区转换,特别是对亚洲时区的处理,他能够将各种时区转换为 UTC 时间。
utcTime, err := asiatz.ShanghaiToUTC("08:00")
if err != nil {
// handle error
}
fmt.Println(utcTime) // Output: 00:00
第 1 步:创建目录
在本地创建一个新的目录,名为 asiatz。这个目录将包含所有的源代码、测试和文档文件。
mkdir asiatz
cd asiatz
第 2 步:初始化项目
2.1 初始化 Go 模块
在 asiatz 目录下,运行 go mod init <domain>/<username>/<module-name> 来初始化 Go 模块。
go mod init github.com/mazeyqian/asiatz
项目结构:
asiatz
└── go.mod
2.2 创建文件
创建一个新的 Go 文件,名为 asiatz.go。在此文件中,定义一个名为 asiatz 的包,并编写相对应的功能函数。
项目结构:
asiatz
├── asiatz.go
└── go.mod
代码示例:
package asiatz
import (
"fmt"
"strconv"
)
// ToUTC converts a time string (HH:mm) from a specified timezone to UTC time string (HH:mm).
func ToUTC(timezoneOffset float64, time string) (string, error) {
hour, err := strconv.Atoi(time[:2])
if err != nil {
return "", err
}
minute, err := strconv.Atoi(time[3:])
if err != nil {
return "", err
}
totalMinutes := hour*60 + minute
utcTotalMinutes := ((totalMinutes-int(timezoneOffset*60))%1440 + 1440) % 1440
utcHour := utcTotalMinutes / 60
utcMinute := utcTotalMinutes % 60
utcTime := fmt.Sprintf("%02d:%02d", utcHour, utcMinute)
return utcTime, nil
}
// ShanghaiToUTC converts a Shanghai time string (HH:mm) to UTC time string (HH:mm).
// For example, "08:00" in Shanghai is equivalent to "00:00" in UTC.
func ShanghaiToUTC(shanghaiTime string) (string, error) {
return ToUTC(8, shanghaiTime)
}
第 3 步:编写测试
Go 提供了内置的测试框架,可以方便地编写和运行测试用例,以确保代码的正确性和稳定性。
在 asiatz 目录下创建一个新的 Go 文件,名为 asiatz_test.go。在这个文件中编写测试用例来测试 asiatz.go 中的函数。
项目结构:
asiatz
├── asiatz.go
├── asiatz_test.go
└── go.mod
代码示例:
package asiatz
import "testing"
type testConversion struct {
time string
expected string
}
var tests = map[string][]testConversion{
"Shanghai": {
{"01:00", "17:00"},
{"23:59", "15:59"},
},
// Others
}
func runConversionTests(t *testing.T, tests []testConversion, conversionFunc func(string) (string, error)) {
for _, test := range tests {
actual, err := conversionFunc(test.time)
if err != nil {
t.Errorf("Unexpected error for %s: %v", test.time, err)
continue
}
if actual != test.expected {
t.Errorf("Expected %s for %s but got %s", test.expected, test.time, actual)
}
}
}
func TestAllConversions(t *testing.T) {
for timezone, tests := range tests {
t.Run(timezone, func(t *testing.T) {
switch timezone {
case "Shanghai":
runConversionTests(t, tests, ShanghaiToUTC)
// Others
default:
t.Errorf("Unexpected timezone %s", timezone)
}
})
}
}
查看完整的用例可见:github.com/mazeyqian/asiatz/blob/main/asiatz_test.go
在当前目录下运行 go test 查看结果:
PASS
ok github.com/mazeyqian/asiatz 0.449s
第 4 步:编写文档
为了方便其他人理解和使用 Asiatz 库,需要编写相应的使用文档。文档应包括库的目的、功能函数的用法、使用示例和注意事项等。
在 asiatz 目录下,创建一个新的 README.md 文件,并在其中编写文档。
项目结构:
asiatz
├── asiatz.go
├── asiatz_test.go
├── go.mod
└── README.md
文档示例:

第 5 步:发布
5.1 上传

将 Asiatz 库上传到 GitHub 或其他代码托管平台,使其他人可以方便地获取和使用。
go get github.com/mazeyqian/asiatz
5.2 版本控制

在 Git 仓库上,还可以使用标签来管理库的不同版本。
git tag v1.0.0
git push origin v1.0.0
例如 Asiatz 目前有四个版本:v1.0.0、v1.1.0、v1.1.1、v1.1.2,分别可以用以下命令获取:
go get github.com/mazeyqian/asiatz@v1.0.0
go get github.com/mazeyqian/asiatz@v1.1.0
go get github.com/mazeyqian/asiatz@v1.1.1
go get github.com/mazeyqian/asiatz@v1.1.2
第 6 步:在真实项目中使用
以 Go 项目 github.com/mazeyqian/go-gin-gee 为例,首先在项目目录(go-gin-gee)下运行命令 go get github.com/mazeyqian/asiatz 获取 Asiatz 库,然后引入使用即可:
// https://github.com/mazeyqian/go-gin-gee/blob/main/internal/api/controllers/schedules-controller.go
package controllers
import (
"log"
"github.com/mazeyqian/asiatz"
)
func Check() {
// ...
utcTime, err := asiatz.ShanghaiToUTC("10:00")
if err != nil {
// handle error
}
log.Println("UTC Time:", utcTime) // Output: 02:00
// ...
}
总结
本文以 Asiatz 库为例,详细演示了如何从零开始创建、测试并发布自己的 Go 库。无论是新手,还是有经验的开发者;动手实践,开发并发布自己的库,不仅可以提高代码的复用性和维护性,提高自己的技能,还可以为社区做出贡献。
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者后除和本文原始地址:https://blog.mazey.net/4150.html
(完)
【Go 编程实践】从零到一:创建、测试并发布自己的 Go 库的更多相关文章
- Robotium实践之路源码创建测试项目
1.JDK安装及环境配置 2.Eclipse安装 3.ADT插件安装 4.模拟器安装 5.准备源码 6.引进源码置项目中 .文件 .导入 .选择现有项目置工作空间中 .浏览 .选择项目,选择模拟器版本 ...
- Robotium实践之路基于APK创建测试项目
1.重新对包进行签名操作 .启动re-sign.jar文件 .找到相应的APK,拖拽置resigner中 2.创建基于APK测试的测试工程 .新建一个安卓测试项目 .选择this project
- 《编写可维护的JavaScript》之编程实践
最近读完<编写可维护的JavaScript>,让我受益匪浅,它指明了编码过程中,需要注意的方方面面,在团队协作中特别有用,可维护性是一个非常大的话题,这本书是一个不错的起点. 本书虽短,却 ...
- 【读书笔记】读《编写可维护的JavaScript》 - 编程实践(第二部分)
本书的第二个部分总结了有关编程实践相关的内容,每一个章节都非常不错,捡取了其中5个章节的内容.对大家组织高维护性的代码具有辅导作用. 5个章节如下—— 一.UI层的松耦合 二.避免使用全局变量 三.事 ...
- 高性能javascript学习笔记系列(5) -快速响应的用户界面和编程实践
参考高性能javascript 理解浏览器UI线程 用于执行javascript和更新用户界面的进程通常被称为浏览器UI线程 UI线程的工作机制可以理解为一个简单的队列系统,队列中的任务按顺序执行 ...
- 编程实践中C语言的一些常见细节
对于C语言,不同的编译器采用了不同的实现,并且在不同平台上表现也不同.脱离具体环境探讨C的细节行为是没有意义的,以下是我所使用的环境,大部分内容都经过测试,且所有测试结果基于这个环境获得,为简化起见, ...
- 第二章 C语言编程实践
上章回顾 宏定义特点和注意细节 条件编译特点和主要用处 文件包含的路径查询规则 C语言扩展宏定义的用法 第二章 第二章 C语言编程实践 C语言编程实践 预习检查 异或的运算符是什么 宏定义最主要的特点 ...
- Python GUI编程实践
看完了<python编程实践>对Python的基本语法有了一定的了解,加上认识到python在图形用户界面和数据库支持方面快捷,遂决定动手实践一番. 因为是刚接触Python,对于基本的数 ...
- C# socket编程实践
C# socket编程实践——支持广播的简单socket服务器 在上篇博客简单理解socket写完之后我就希望写出一个websocket的服务器了,但是一路困难重重,还是从基础开始吧,先搞定C# ...
- HBase Coprocessor 剖析与编程实践(转载http://www.cnblogs.com/ventlam/archive/2012/10/30/2747024.html)
HBase Coprocessor 剖析与编程实践 1.起因(Why HBase Coprocessor) HBase作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执行求和. ...
随机推荐
- snmptt解析中文trap消息
项目中使用了中国电信系统集成公司的虚拟化平台,为通过zabbix监控,接收HyperCenter发送的告警,需要将trap消息中的汉语编码转译.网络上snmptt资料不多,官网文档也不甚友好,通过参考 ...
- zabbix6.4 邮件告警配置
1.注意事项 QQ邮箱不支持zabbix6以上邮件配置,报拒绝登录 建议使用163.com网易邮箱地址 2.添加媒介 创建媒介类型-> 3.添加用户 一般情况下,无需创建用户,编辑admin即可 ...
- hive grouping set
reference https://www.cnblogs.com/erlou96/p/13564191.html data-demo 2015-03,2015-03-10,cookie1 2015- ...
- 2023-08-20:用go语言写算法。给定一个由'W'、'A'、'S'、'D'四种字符组成的字符串,长度一定是4的倍数, 你可以把任意连续的一段子串,变成'W'、'A'、'S'、'D'组成的随意状
2023-08-20:用go语言写算法.给定一个由'W'.'A'.'S'.'D'四种字符组成的字符串,长度一定是4的倍数, 你可以把任意连续的一段子串,变成'W'.'A'.'S'.'D'组成的随意状态 ...
- 文心一言 VS 讯飞星火 VS chatgpt (79)-- 算法导论7.4 4题
四.请用go语言,证明:RANDOMIZED-QUICKSORT 期望运行时间是 Ω(nlgn). 文心一言: 首先,为了证明RANDOMIZED-QUICKSORT的期望运行时间是Ω(nlg n), ...
- U268603 I Hate This Tree 题解
传送门 一道纯粹的码力 + 卡常题. 前置 矩阵乘法,线段树. 分析 线段树存矩阵. 构造迭代矩阵: \[\begin{pmatrix}f_i&f_{i-1}\end{pmatrix}\tim ...
- [ABC150F] Xor Shift
2023-03-10 题目 题目传送门 翻译 翻译 难度&重要性(1~10):6 题目来源 AtCoder 题目算法 KMP,Z函数 解题思路 首先是按位确定,令 \(t(i,j)\) 表示 ...
- redis分布式锁,setnx+lua脚本的java实现
1 前言 在现在工作中,为保障服务的高可用,应对单点故障.负载量过大等单机部署带来的问题,生产环境常用多机部署.为解决多机房部署导致的数据不一致问题,我们常会选择用分布式锁. 目前其他比较常见的实现方 ...
- PHP调用API接口的方法及实现
随着互联网.云计算和大数据时代的到来,越来越多的应用程序需要调用第三方的API接口来获取数据,实现数据互通和协同工作.PHP作为一种常用的服务器端语言,也可以通过调用API接口来实现不同系统的数据交互 ...
- 拓展kmp
Smiling & Weeping ---- 我从不觉得暗恋是苦涩的, 对一个人的喜欢藏在眼睛里, 透过它, 世界都变得更好看了. 题目:P5410 [模板]扩展 KMP(Z 函数) - 洛谷 ...