go mod

go mod

————

————

Usage:

    go mod <command> [arguments]
命令说明
downloaddownload modules to local cache(下载依赖包)
editedit go.mod from tools or scripts(编辑go.mod)
graphprint module requirement graph (打印模块依赖图)
verifyinitialize new module in current directory(在当前目录初始化mod)
tidyadd missing and remove unused modules(拉取缺少的模块,移除不用的模块)
vendormake vendored copy of dependencies(将依赖复制到vendor下)
verifyverify dependencies have expected content (验证依赖是否正确)
whyexplain why packages or modules are needed(解释为什么需要依赖)

使用go mod管理一个新项目

初始化项目

D:\study\go_study\example01>go mod init example01
go: creating new go.mod: module example01

go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。

查看go.mod

module example01

go 1.15

go.mod 提供了module, require、replace和exclude 四个命令

  • module 语句指定包的名字(路径)
  • require 语句指定的依赖项模块
  • replace 语句可以替换依赖项模块
  • exclude 语句可以忽略依赖项模块

添加依赖

创建main.go 文件

package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

执行 go run main.go 运行代码会发现 go mod 会自动查找依赖自动下载

  • 问题一:依赖的包下载到哪里了?还在GOPATH/src里吗?

不在。
使用Go的包管理方式,依赖的第三方包被下载到了$GOPATH/pkg/mod路径下。

再查看 go.mod

module example01

go 1.15

require github.com/gin-gonic/gin v1.6.3

go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit

go 会自动生成一个 go.sum 文件来记录 dependency tree

img

再次执行脚本 go run main.go发现跳过了检查并安装依赖的步骤。

可以使用命令 go list -m -u all 来检查可以升级的package,使用go get -u need-upgrade-package 升级后会将新的依赖版本更新到go.mod * 也可以使用 go get -u 升级所有依赖

go get升级

  • 运行 go get -u 将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
  • 运行 go get -u=patch 将会升级到最新的修订版本
  • 运行 go get package@version 将会升级到指定的版本号version
  • 运行go get如果有版本的更改,那么go.mod文件也会更改

使用replace替换无法直接获取的package

由于某些已知的原因,并不是所有的package都能成功下载,比如:golang.org下的包。

modules 可以通过在 go.mod 文件中使用 replace 指令替换成github上对应的库,比如:

replace (
    golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
)

go mod发布和使用

creating a module

如果你设置好go mod了,那你就可以在任何目录下随便创建

$mkdir gomodone
$cd gomodone

在这个目录下创建一个文件say.go

package gomodone

import "fmt" 

// say Hi to someone
func SayHi(name string) string {
   return fmt.Sprintf("Hi, %s", name)
}

初始化一个 go.mod文件

$ go mod init github.com/jacksonyoudi/gomodone
go: creating new go.mod: module github.com/jacksonyoudi/gomodone

查看 go.mod内容如下:

github.com/jacksonyoudi/gomodone
go 1.14

下面我们要将这个module发布到github上,然后在另外一个程序使用

$git init
$vim .gitiiignore
$git commit -am "init"
// github创建对应的repo
$git remote add origin git@github.com:jacksonyoudi/gomodone.git
$git push -u origin master

执行完,上面我们就相当于发布完了。

如果有人需要使用,就可以使用

go get github.com/jacksonyoudi/gomodone

这个时候没有加tag,所以,没有版本的控制。默认是v0.0.0后面接上时间和commitid。如下:

gomodone@v0.0.0-20200517004046-ee882713fd1e

module versioning

使用tag,进行版本控制

making a release

git tag v1.0.0
git push --tags

操作完,我们的module就发布了一个v1.0.0的版本了。

推荐在这个状态下,再切出一个分支,用于后续v1.0.0的修复推送,不要直接在master分支修复

$git checkout -b v1
$git push -u origin v1

use our module

上面已经发布了一个v1.0.0的版本,我们可以在另一个项目中使用,创建一个go的项目

$mkdir Gone
$cd Gone
$vim main.go
package main

import (
    "fmt"
    "github.com/jacksonyoudi/gomodone"
)

func main() {
    fmt.Println(gomodone.SayHi("Roberto"))
}

代码写好了,我们生成 go mod文件

go mod init Gone

上面命令执行完,会生成 go mod文件
看下mod文件:

module Gone

go 1.14

require (
    github.com/jacksonyoudi/gomodone v1.0.0
)
$go mod tidy
go: finding module for package github.com/jacksonyoudi/gomodone
go: found github.com/jacksonyoudi/gomodone in github.com/jacksonyoudi/gomodone v1.0.0

同时还生成了go.sum, 其中包含软件包的哈希值,以确保我们具有正确的版本和文件。

github.com/jacksonyoudi/gomodone v1.0.1 h1:jFd+qZlAB0R3zqrC9kwO8IgPrAdayMUS0rSHMDc/uG8=
github.com/jacksonyoudi/gomodone v1.0.1/go.mod h1:XWi+BLbuiuC2YM8Qz4yQzTSPtHt3T3hrlNN2pNlyA94=
github.com/jacksonyoudi/gomodone/v2 v2.0.0 h1:GpzGeXCx/Xv2ueiZJ8hEhFwLu7xjxLBjkOYSmg8Ya/w=
github.com/jacksonyoudi/gomodone/v2 v2.0.0/go.mod h1:L8uFPSZNHoAhpaePWUfKmGinjufYdw9c2i70xtBorSw=

这个内容是下面的,需要操作执行的结果

go run main.go就可以运行了

Making a bugfix release

假如fix一个bug,我们在v1版本上进行修复

修改代码如下:

// say Hi to someone
func SayHi(name string) string {
-       return fmt.Sprintf("Hi, %s", name)
+       return fmt.Sprintf("Hi, %s!", name)
}

修复好,我们开始push

$ git commit -m "Emphasize our friendliness" say.go
$ git tag v1.0.1
$ git push --tags origin v1

Updating modules

刚才fix bug,所以要在我们使用项目中更新

这个需要我们手动执行更新module操作

我们通过使用我们的好朋友来做到这一点go get:

  • 运行 go get -u 以使用最新的 minor 版本或修补程序版本(即它将从1.0.0更新到例如1.0.1,或者,如果可用,则更新为1.1.0)
  • 运行 go get -u=patch 以使用最新的 修补程序 版本(即,将更新为1.0.1但不更新 为1.1.0)
  • 运行go get package@version 以更新到特定版本(例如github.com/jacksonyoudi/gomodone@v1.0.1

目前module最新的也是v1.0.1

// 更新最新
$go get -u
$go get -u=patch
//指定包,指定版本
$go get github.com/jacksonyoudi/gomodone@v1.0.1

操作完,go.mod文件会修改如下:

module Gone

go 1.14

require (
    github.com/jacksonyoudi/gomodone v1.0.1
)

Major versions

根据语义版本语义,主要版本与次要版本 不同。主要版本可能会破坏向后兼容性。从Go模块的角度来看,主要版本是 完全不同的软件包。乍一看这听起来很奇怪,但这是有道理的:两个不兼容的库版本是两个不同的库。

比如下面修改,完全破坏了兼容性。

package gomodone

import (
    "errors"
    "fmt"
)

// Hi returns a friendly greeting
// Hi returns a friendly greeting in language lang
func SayHi(name, lang string) (string, error) {
    switch lang {
    case "en":
        return fmt.Sprintf("Hi, %s!", name), nil
    case "pt":
        return fmt.Sprintf("Oi, %s!", name), nil
    case "es":
        return fmt.Sprintf("¡Hola, %s!", name), nil
    case "fr":
        return fmt.Sprintf("Bonjour, %s!", name), nil
    default:
        return "", errors.New("unknown language")
    }
}

如上,我们需要不同的大版本,这种情况下

修改 go.mod如下

module github.com/jacksonyoudi/gomodone/v2

go 1.14

然后,重新tag,push

$ git commit say.go -m "Change Hi to allow multilang"
$ git checkout -b v2 # 用于v2版本,后续修复v2
$ git commit go.mod -m "Bump version to v2"
$ git tag v2.0.0
$ git push --tags origin v2

Updating to a major version

即使发布了库的新不兼容版本,现有软件 也不会中断,因为它将继续使用现有版本1.0.1。go get -u 将不会获得版本2.0.0。
如果想使用v2.0.0,代码改成如下.

package main

import (
    "fmt"
    "github.com/jacksonyoudi/gomodone/v2"
)

func main() {
    g, err := gomodone.SayHi("Roberto", "pt")
    if err != nil {
        panic(err)
    }
    fmt.Println(g)
}

执行 go mod tidy

go: finding module for package github.com/jacksonyoudi/gomodone/v2
go: downloading github.com/jacksonyoudi/gomodone/v2 v2.0.0
go: found github.com/jacksonyoudi/gomodone/v2 in github.com/jacksonyoudi/gomodone/v2 v2.0.0

当然,两个版本都可以同时使用, 使用别名
如下:

package main

import (
    "fmt"
    "github.com/jacksonyoudi/gomodone"
    mv2 "github.com/jacksonyoudi/gomodone/v2"
)

func main() {
    g, err := mv2.SayHi("Roberto", "pt")
    if err != nil {
        panic(err)
    }
    fmt.Println(g)

    fmt.Println(gomodone.SayHi("Roberto"))
}

Vendoring

默认是忽略vendor的,如果想在项目目录下有vendor可以执行下面命令

$go vendor

当然,如果构建程序的时候,希望使用vendor中的依赖,

$ go build -mod vendor

IDEA下开发GO

  • 创建go项目

img

  • 创建完项目,会自动生成go mod文件
    如果需要修改,可以手动修改,加入git等操作

  • 写业务逻辑代码

img

  • 解决依赖,更新go.mod

img

  • go build

n(gomodone.SayHi(“Roberto”))
}


### Vendoring

默认是忽略vendor的,如果想在项目目录下有vendor可以执行下面命令

```bash
$go vendor

当然,如果构建程序的时候,希望使用vendor中的依赖,

$ go build -mod vendor

IDEA下开发GO

  • 创建go项目

[外链图片转存中…(img-13khfPBg-1675928204799)]

  • 创建完项目,会自动生成go mod文件
    如果需要修改,可以手动修改,加入git等操作

  • 写业务逻辑代码

[外链图片转存中…(img-NO3dkIAi-1675928204803)]

  • 解决依赖,更新go.mod

[外链图片转存中…(img-PwGP9cU8-1675928204804)]

  • go build
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值