go 使用 gitlab 搭建私有化模块系统

背景

本教程旨在教大家使用私有化部署的 gitlab 作为 go 的代码共享库,帮助团队分离代码模块,加强质量管控。go 官方在实现过程中就高度结合 VCS 系统,
可以仅通过配置相关的环境变量就实现私有库在 VCS 上的搭建。

代码分离样例

这里直接举出各种开发场景,提供开箱即用的案例参考,内部核心原理最后部分再讲。

案例1: 我会使用 gitlab, 我只想提交代码,不想搞什么 go 的配置

摘要

gitlab 拉下来的代码是一个独立的目录,建立对这个目录的依赖就可以使用这个模块的代码

## 配置项目对 example.com/project2 的包依赖定位到本地代码目录中
go mod edit -replace example.com/project2=../project2## replace 完还需要手动 go get 来建立依赖关系
go get example.com/project2
案例讲解

这里从零创建两个独立模块 project1, project2 来讲解。至于 gitlab 拉取的项目也是一个独立的目录,按照下面的方法建立本地依赖即可。

在这里插入图片描述

project1, project2 分别初始化

C:\Project\code-all\project1> go mod init example.com/project1
go: creating new go.mod: module example.com/project1C:\Project\code-all\project2> go mod init example.com/project2
go: creating new go.mod: module example.com/project2

在项目 project2 中新建自己的模块文件,暴露自己的公有函数

project2/result.go

package myfuncfunc HelloProject2() string {return "这里是 project2 的工具方法"
}

在项目 project1 中导入模块 example.com/project2,使用暴露的方法

注意,直接这么写还不能让 go 正确定位模块,IDE 也会缺少语法提示

project1/main.go

package mainimport ("fmt"myfunc "example.com/project2"
)func main() {fmt.Print(myfunc.HelloProject2())
}

对本地分离的代码模块,go 提供 go mod edit -replace 指令来进行依赖管理。
我们在 project1 中使用该指令添加本地代码依赖

## 配置项目对 example.com/project2 的包依赖定位到本地代码目录中
go mod edit -replace example.com/project2=../project2## replace 完还需要手动 go get 来建立依赖关系
go get example.com/project2

执行结果

C:\Project\code-all\project1> go mod edit -replace example.com/project2=../project2
C:\Project\code-all\project1> go get example.com/project2
go get: added example.com/project2 v0.0.0-00010101000000-000000000000
C:\Project\code-all\project1> 

现在运行 project1/main.go,可以看到 myfunc 包的函数被正常调用了

C:\Project\code-all\project1> go run .\main.go
这里是 project2 的工具方法
拓展

这个案例讲解的是怎么把本地的代码模块作为依赖添加到项目中。
go 官方推荐的用法是用这个 replace 方法做一些工具库的调试。
比如你依赖了一个流行的库,可以用这个方法在不改变主工程代码 import 语句的情况下,将库的代码手动拉下来,然后建立本地依赖进行调试。

官方举例:

replace golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5replace (golang.org/x/net v1.2.3 => example.com/fork/net v1.4.5golang.org/x/net => example.com/fork/net v1.4.5golang.org/x/net v1.2.3 => ./fork/netgolang.org/x/net => ./fork/net
)

更多讲解查阅 https://go.dev/ref/mod#go-mod-file-replace

案例2:我不想把项目代码拉到本地来建立依赖,能不能像使用其他库那样直接从网络拉取

摘要

go 一开始就深度结合了 VCS 系统,提供了非常简便的环境变量配置来完成模块私有化的问题

## 配置私有域名,go 查找依赖时就不会经过 GOPROXY
go env -w GOPRIVATE=gitlab.b.com## gitlab 没有配置 https 的话, 还需要配置域名让 go 拉包时发 http
go env -w GOINSECURE=gitlab.b.com## 加一个不做公共校验的配置
go env -w GONOSUMDB=gitlab.b.com## 创建 gitlab 仓库,将我们需要共享的库代码的 module 改为 gitlab 仓库地址
## 举例
module gitlab.b.com/c/test-helloworld.git## 新建一个 gitlab 仓库 test-helloworld ,可见性设为 public, 上传自己的模块代码,
## 现在可以直接中 gitlab 拉取模块代码了
## 注意,模块地址后面要用 .git 结尾,不然拉取模块走的是 HTTP GET
go get gitlab.b.com/c/test-helloworld.git
案例讲解

案例1 中我们讲解了怎么建立对本地模块的依赖,或者说对独立拉取的 gitlab 项目代码的依赖。replace 方式并不是官方推崇的模块私有化方法。因为这样每次模块代码更新了,你都要手动在本地的目录中同步更新。目前网络上主流的模块升级方法是在项目中更改一下版本号后重新拉取模块即可。

go 的底层已经针对各种 VCS 系统 (.bzr, .fossil, .git, .hg, .svn)做了适配,可以简单的从模块地址是否以 VCS 后缀结尾来选择模块拉取逻辑

首先我们要配置我们的内部仓库域名为私有域名,一般 go 项目配置的代理 GOPROXYhttps://goproxy.cn,direct

所以需要配置私有域名,绕过我们配置的代理

go env -w GOPRIVATE=gitlab.b.com

gitlab 没有配置 https 的话, 需要配置域名让 go 拉包时发 http

go env -w GOINSECURE=gitlab.b.com

搭配不做公共校验的配置

go env -w GONOSUMDB=gitlab.b.com

接下来就是重点了,我们一定要对线上的模块打 git tag 标签,go 才能正常的完成拉取。我们下载 go 依赖时一般也会写上版本号,这个版本号就是 git tag 的对应名字。默认是 latest

下面我们试着将上面创建的 project2 上传到 gitlab 进行共享

cd ..\project2\
git init .
git add .
git commit -m "init"
git remote add origin ssh://git@gitlab.b.com:11111/c/go-test-project2.git
git push origin master

现在 gitlab 线上已经有我们的代码了,但这时还没有打 tag
在这里插入图片描述
完成了上面的环境变量设置后,我们在 project1 移除 replace 后再用 go get 来拉取我们的线上模块

不出意外报错了

C:\Project\code-all\project1> go get gitlab.b.com/c/go-test-project2
go get: unrecognized import path "gitlab.b.com/c/go-test-project2": 
parse http://gitlab.b.com/c/go-test-project2?go-get=1: 
no go-import meta tags (meta tag gitlab.b.com:81/c/go-test-project2 did not match 
import path gitlab.b.com/c/go-test-project2)

这里直接讲分析
当拉去一个模块时,如果模块的 URL 地址 gitlab.b.com/c/go-test-project2 后面没有携带 VCS 后缀(如 .git, .svn),go 将通过 HTTP GET 的方式去请求模块代码,发出的请求如:
http://gitlab.b.com/c/go-test-project2?go-get=1

会携带上 go-get=1 作为标志。一般的解决方法是 nginx 做一个反向代理,伪造正常响应来处理。但是内部配置的 gitlab 运行在非 80 端口上时,对 80 的访问会收到重定向的响应。这也是 go 会去请求 gitlab.b.com:81/c/go-test-project2 的原因。

但是 go 内部的包路径不允许携带端口在 URL 中,所以就中断了拉取流程。

而当包的 URL 携带了 .git 时,go 会进入直连模式,并且使用 git 来拉取代码。我们试一下

C:\Project\code-all\project1> go get gitlab.b.com/c/go-test-project2.git 
go: downloading gitlab.b.com/c/go-test-project2.git v0.0.0-20240726024502-c0914057a375
go get: gitlab.b.com/c/go-test-project2.git@v0.0.0-20240726024502-c0914057a375: parsing go.mod:module declares its path as: example.com/project2but was required as: gitlab.b.com/c/go-test-project2.git

可以发现现在 go 可以正常下载仓库代码,但是进行模块分析时报错,显示我们请求的模块路径和模块自己声明的路径不一致。我们模块里面写的 example.com/project2,但是请求是用的 gitlab.b.com/c/go-test-project2.git

所以我们修改 project2 的 module 为 gitlab.b.com/c/go-test-project2.git,然后提交到 gitlab 后重新拉取。

project2/go.mod

module gitlab.b.com/c/go-test-project2.gitgo 1.17

现在重新拉取,可以看到模块被成功拉到本地了,而且是 go 去管理

C:\Project\code-all\project1> go get gitlab.b.com/c/go-test-project2.git 
go: downloading gitlab.b.com/c/go-test-project2.git v0.0.0-20240726030655-fa5e48794cf3
go get: added gitlab.b.com/c/go-test-project2.git v0.0.0-20240726030655-fa5e48794cf3

至此,已经完成了模块私有化的全部流程。

拓展

为了更好的对代码进行版本控制,标准的流程是在拉起 go 的模块时,需要携带版本号。这里演示一下怎么建立版本号:

首先在 project2 项目中打一个 git tag

C:\Project\code-all\project2> git tag -a v1.0.0 -m 'my version 1.0.0' 
C:\Project\code-all\project2> git show v1.0.0
tag v1.0.0
Tagger: c<c@b.org>
Date:   Fri Jul 26 11:17:28 2024 +0800my version 1.0.0
tag v1.0.0
Tagger: c<c@b.org>

然后将这个 tag 发布到线上

C:\Project\code-all\project2> git push origin v1.0.0
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 160 bytes | 160.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To ssh://gitlab.b.com:10022/c/go-test-project2.git* [new tag]         v1.0.0 -> v1.0.0

现在我们可以用版本号来拉取代码了,可以看到 go 自动帮我们更新了依赖的版本

C:\Project\code-all\project1> go get gitlab.b.com/c/go-test-project2.git@v1.0.0
go: downloading gitlab.b.com/c/go-test-project2.git v1.0.0
go get: upgraded gitlab.b.com/c/go-test-project2.git v0.0.0-20240726030655-fa5e48794cf3 => v1.0.0

更多 go get 版本控制查阅
https://pkg.go.dev/cmd/go#hdr-Add_dependencies_to_current_module_and_install_them

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虚幻5|制作玩家血量,体力(还未编辑,只用于引用)

未编写&#xff0c;仅引用 优化后&#xff1a; 把增加生命&#xff0c;减少生命&#xff0c;也可以用在体力里&#xff0c;更改如下 限制浮点&#xff0c;如果血量或体力按10来扣&#xff0c;如果你的血量降低到5&#xff0c;那么就会以5的数值来扣&#xff0c;而不会扣成-5…

JVM极简教程

基础概念 1.1. Java 虚拟机 是运行 Java字节码的虚拟机 1.2. JVM跨平台原理 JVM在不同的系统&#xff08;Linux、Windows、MacOS&#xff09;上有不同的实现&#xff0c;目的是在使用相同的字节码&#xff0c;它们都会给出相同的结果 JVM跨平台本质&#xff1a;不同操作系统…

如何满足业主多元需求?开发物业APP,打造智能社区生活

随着智能科技的快速发展&#xff0c;物业管理也逐渐迈入数字化时代。物业app开发成为了提升社区管理效率、改善居民生活质量的重要途径&#xff0c;许多物业管理公司纷纷开发物业App&#xff0c;以提升管理效率、改善用户体验。一款出色的物业APP能够整合居民需求、提升企业服务…

Mybatis进阶——动态SQL

动态SQL 是Mybatis的强大特性之一&#xff0c;能够完成不同条件下的不同SQL拼接&#xff0c;可以参考官方文档&#xff1a;动态 SQL_MyBatis中文网 xml文件内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper PUBLI…

uniapp/uniapp x总结

uni-app组成和跨端原理 上图所诉 App的渲染引擎&#xff1a;同时提供了2套渲染引擎&#xff0c;.vue页面文件由webview渲染&#xff0c;原理与小程序相同&#xff1b;.nvue页面文件由原生渲染&#xff0c;原理与react native相同。开发者可以根据需要自主选择渲染引擎。 uniapp…

52.给定一个整数 n,实现一个算法返回 n 皇后不同的解决方案的数量

52. N-Queens II 题目 n皇后问题是指将n个皇后放置在一个nn的棋盘上,使得任意两个皇后不在同一行、同一列或同一对角线上。 给定一个整数 n,返回 n 皇后问题不同的解法数量。 示例: 输入: 4 输出: 2 解释: 4皇后问题有如下两个不同的解法: [ [“.Q…”, // 解法 1 “……

sqli-labs靶场通关攻略(36-40关)

第36关&#xff08;宽字节注入&#xff08;Bypass MySQL Real Escape String&#xff09;&#xff09; 查数据库 ?id-1%df%27%20union%20select%202,database(),3%20-- 查表 ?id-1%df union select 1,group_concat(table_name),3 from information_schema.tables where tab…

Python青少年简明教程:列表(List)、元组(tuple)和字典(dict)

Python青少年简明教程&#xff1a;列表&#xff08;List&#xff09;、元组&#xff08;tuple&#xff09;和字典&#xff08;dict&#xff09; 在Python中&#xff0c;列表&#xff08;List&#xff09;、元组&#xff08;Tuple&#xff09;和字典&#xff08;Dict&#xff09…

Ubuntu下部署Hadoop集群+Hive(三)

Hive部署 准备环境 apache-hive-4.0.0-bin.tar.gz、mysql-connector-j-8.1.0.jar 如果是离线安装的话&#xff0c;使用mysql-8.0.34-1.el7.x86_64.rpm-bundle.tar&#xff0c;在线安装的话则不用&#xff1b; hive下载地址&#xff1a;Index of /hive (apache.org) mysql …

机械学习—零基础学习日志(如何理解概率论9)

大数定律与中心定律 来看一道习题&#xff1a; 这个题目看看&#xff0c;应该是什么呢~下一章来看看解析~ 《概率论与数理统计期末不挂科|考研零基础入门4小时完整版&#xff08;王志超&#xff09;》学习笔记 王志超老师 &#xff08;UP主&#xff09;

vue3 + ElImage + nodejs 集成了看板娘(UI原生开发达99%)的响应式BLOG(个人博客)。

一、想要我的屎山代码&#xff0c;可以私聊我哟 访问地址&#xff0c;欢迎访问&#xff08;访问效果更佳&#xff09; ☂ 被你发现了&#xff01;&#xff5c; snows_ls BLOGhttp://124.223.41.220/ 欢迎互挂友链 二、做了个啥 1、看板娘&#xff08;看效果好吧&#xff09;…

【数据结构】线性表的顺序表示(顺序表的定义和基本操作)

计算机考研408-数据结构笔记本之——第二章 线性表 2.2 线性表的顺序表示&#xff08;顺序表的定义和基本操作&#xff1a;初始化/插入/删除/查找&#xff09; 2.2.1 顺序表的定义 1.定义 顺序表是线性表的顺序存储。 所谓顺序存储&#xff0c;就是把逻辑上相邻的元素存储在物…

C++ 设计模式——享元模式

C 设计模式——享元模式 C 设计模式——享元模式1. 主要组成成分2. 享元模式内部状态3. 享元模式外部状态4. 逐步构建享元模式4.1 抽象享元类定义4.2 具体享元类实现4.3 享元工厂类实现4.4 主函数 5. 享元模式 UML 图享元模式 UML 图解析 6. 享元模式的优点7. 享元模式的缺点8.…

Linux驱动学习之中断与等待队列

本篇分为设备树部分和API接口部分 设备树 想要使用中断&#xff0c;设备树中需要有两个属性&#xff1a; interrupts // 表示要使用哪一个中断, 中断的触发类型等等。 interrupt-parent // 这个中断要接到哪一个设备去? 即父中断控制器是谁 父中…

趣味算法------拯救阿拉德大陆

目录 ​编辑 题目描述&#xff1a; 思路解析&#xff1a; 具体代码&#xff1a; 总结&#xff1a; 题目描述&#xff1a; 此时一批勇士也随之而来&#xff0c;但其能力也是参差不齐&#xff0c;我们需要挑选出最优秀的勇士来守护这片大陆。每位勇士都有属于自己的编号&am…

JobSchedulerService.setRequiresCharging需充电且电量大于90%才触发的现象

一、摘要 从源码看原生JobSchedulerService.setRequiresCharging 的特性&#xff0c;该特性竞品机器华为、Oppo也是如此。 1、应用处于前台可见&#xff0c;满足充电条件&#xff0c;立刻触发 2、应用处于后台不可见&#xff0c;需要设备连接USB或AC且电量大于90%&#xff0…

挂个人-CSDN Java优秀内容博主rundreamsFly抄袭

事件起因 今天点开自己的CSDN博客&#xff0c;发现给我推了一篇文章抄袭我自己昨天18点发的文章。 就是这篇&#xff0c;一字不差&#xff0c;博主昵称是&#xff1a;rundreamsFly&#xff0c;账号是rundreams。 抄袭者文章 发布于2024-8-26 19:37:41秒&#xff0c;比我发布…

C的温故而知新:位操作(C Primer Plus第十五章)

第十五章&#xff1a;位操作 这一章的篇幅不是很长&#xff0c;但既然能单独作为一章来讲的话&#xff0c;应该蛮重要的&#xff0c;但是我貌似没有总结出多少需要注意、加强记忆的东西&#xff0c;可见在JAVA的日常开发过程中基本不太遇见有关位操作的内容&#xff0c;所以我…

FSQ26信号分析仪RS FSU26 20HZ-26.5G频谱分析仪

罗德与施瓦茨Rohde & Schwarz FSQ26信号分析仪&#xff0c;20 Hz - 26.5 GHz ​R&S FSQ26 信号分析仪集两种仪器于一身。它提供高达 120 MHz 解调带宽的信号分析&#xff0c;并具有高端频谱分析仪的动态范围。 频率范围&#xff1a;20 Hz 至 26.5 GHz 高端频谱分析仪…

神经网络—卷积层

1.讲解 Conv2d out_channels 参数为2时&#xff0c;会生成两个卷积核&#xff0c;分别与输入进行卷积。得到的两个输出为输出 新生成的卷积核和原来的卷积核不一定相同 in_channels (int) – Number of channels in the input image out_channels (int) – Number of channels…