【Go Module系列教程】手把手教你,如何使用Go Module

2023-10-26

【Go Module系列教程】手把手教你如何使用Go Module


请先看我

看了网上的好多中文博客,一直都没有看懂,这个Go Module 到底如何使用。无奈╮(╯▽╰)╭只能去看看官方的教程是怎么样的了。

本文结合 官方文档我自己的实践 ,根据官方文档手动操作了一波Go Module的使用。强烈建议和我一样的小伙伴跟着这篇文章的流程走一遍,肯定有所收货!!!

(文章有点长,慢慢来哈;本人翻译和写作水平有限,如有错误,不吝指正)

个人站点:https://www.quanquanting.com/

简介

这篇博客是【Go Module系列教程】的第一部分,其中包括:

  1. 如何使用Go Module

  2. 如何迁移至Go Module(待更新)

  3. 如何发布Go Module(待更新)

  4. Go Modules: v2 and Beyond(待更新)

Go Module是Golang新的依赖包管理系统,能够直接罗列出依赖包的版本信息且易于管理。在Go 1.11和Go 1.12都已经初步支持Go Module。这篇文章将介绍使用Go Module的基本操作。后续的文章将介绍如何去发布Go Module去给其他人使用。

go.mod文件是在项目的根目录下,是个Go依赖包的集合。这个go.mod文件定义了Go依赖包的路径,也是项目使用的导入路径,还包括使依赖包能够成功构建的依赖需求。每个依赖包都包括一个路径和特定语义版本。

从Go 1.11起,如果目录在$GOPATH/src之外,而且当前的路径或是任何父目录包含go.mod文件时,都可以使用Go Module的命令。相反如果是在$GOPATH/src之中,为了兼容,即使存在go.mod文件,也只能使用原有的GOPATH下的命令。但是从Go 1.13开始,Go Module模式将成为开发的默认模式。

本片文章将介绍开发中一系列常见的操作:

创建一个新Module

让我们创建一个新Module吧

首先需要在$GOPATH/src之外任何地方,创建一个空的目录\hello。进入该目录,在创建一个新的文件hello.go:

package hello 

func Hello() string {
	return "Hello, world."
}

我们再写个测试,hello_test.go:

package hello

import "testing" 

func TestHello(t *testing.T) {
	want := "Hello, world."
	if got := Hello(); got != want {
		t.Errorf("Hello() = %q, want %q", got, want)
	}
}

到目前为止,这个目录下有个依赖包了,但是还不是个Module,因为还没有go.mod文件。如果我们在目录F:\hello下,执行go test,会看到:

F:\hello>go test
PASS
ok      _/F_/hello 0.153s

最后一行显示了当前的测试结果。因为我们既不在$GOPATH/src之中,也没有Module,所以go不知道当前目录的导入路径,只是根据目录名F:\hello创建一个伪目录。

让我们在该目录下通过go mod init命令,是这个依赖包成为一个Module,然后再执行go test

F:\hello>go mod init hello
go: creating new go.mod: module hello

F:\hello>go test
PASS
ok      hello   0.164s

恭喜你!你写了第一个Module,并通过了测试。

go mod init命令自动创建了go.mod文件:

module hello

go 1.12

go.mod文件只会在Module的根目录。子目录中的依赖包的路径是由Module的目录加上子目录的路径组成。举个例子,如果我们创建了子目录world,我们不需要在这个目录下再运行go mod init,这个依赖包会自动被识别为hello Module的一部分,导入路径就是hello/world

添加依赖包

Go Module的主要目的就提升应用其他开发人员的编写的代码的使用体验(就是添加依赖包的体验)。
现在让我们更新一下hello.go,引入rsc.io/quote,并使用引用函数实现Hello函数:

package hello

import "rsc.io/quote"

func Hello() string {
    return quote.Hello()
}

接下来运行一下go test:

F:\hello>go test
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
PASS
ok      hello    0.164s

小知识:以上这一步go test,会自动寻找依赖包,如果你未开代理,应该会出现如下错误:

go: golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c: unrecognized import path "golang.org/x/text" (https fetch: Get https://golang
.org/x/text?go-get=1: dial tcp 216.239.37.1:443: connectex: A connection attempt failed because the connected party did not properly re
spond after a period of time, or established connection failed because connected host has failed to respond.)
go: error loading module requirements

----------------------------------------
https://www.quanquanting.com/
----------------------------------------

如果要继续运行的话,可先配置代理。如果是Windows系统的话,需要在PowerShell中先设置代理:

# 查看
set http_proxy
# 设置
set http_proxy=YOUR-PROXY
set https_proxy=YOUR-PROXY
# 删除
set http_proxy=

例如我的YOUR-PROXYsocks5://127.0.0.1:1080

详细的方法可见==》如何在命令行工具中使用代理?


配置完毕后在运行go test

Go会解析go.mod中所罗列的特定的依赖包并导入。当遇到依赖包被引用,但是不在go.mod之中时,Go会自动查找包含该依赖包的Module并将其添加到go.mod中,默认使用最新的版本(引用顺序为优先寻找“最新标记的稳定版本”,其次寻找“最新发布的预发布版本”,最后时“未标记的版本”)。在我们的例子中,go test命令在导入rsc.io/quote中,导入了rsc.io/quote v1.5.2。同时还下载了两个rsc.io/quote的依赖包,分别是rsc.io/samplergolang.org/x/text。但是只有直接被引用的依赖包被记录到了go.mod文件中:

module hello

go 1.12

require rsc.io/quote v1.5.2

如果再次运行go test不会再重复上面的工作了,因为go mod文件已经在上一次更新了,下载的相应的Module缓存在$GOPATH/pkg/mod中。

F:\hello>go test
PASS
ok      hello   0.174s

这里多说一句,虽然现在Go添加新的依赖包变得更容易了。但是这是有代价的,例如依赖包的质量、安全性和是否授权等,更多详见Russ Cox的文章“Our Software Dependency Problem

正如我们上面所看到的,在直接添加一个依赖包的过程往往还会带来其他依赖包,go list -m all命令可以列出当前的Module以及它所有的依赖包:

F:\hello>go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0

在输出的列表中,当前的Module总是第一行,让后是按照路径排序的依赖包。

其中golang.org/x/text的版本v0.0.0-20170915032832-14c0d48ead0c是一个伪版本的例子,这是Go针对特定的未作标记提交的版本命名。

除了go.mod文件,Go还创建了名为go.sum的文件,该文件包含特定Module版本内容的Hash:

golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

Go使用go.sum文件确保这些Module和第一次下载的相同,防止你的项目所依赖的Module不会因为恶意、意外或其他原因而被更改。所以go.modgo.sum文件都应该加入到你的版本控制中。

升级依赖包

在Go Module中,版本通过语义版本标签引用,一个语义版本有三个部分:major(主版本号)、minor(次版本号)和patch(修订号)。例如,对v0.1.2来说,其major(主版本号)就是0,其minor(次版本号)就是1,其patch(修订号)就是2。让我们先看看几个次版本的升级,在下一节中来考虑主版本的升级。


小知识:
版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

主版本号:当你做了不兼容的 API 修改,
次版本号:当你做了向下兼容的功能性新增,
修订号:当你做了向下兼容的问题修正。

先行版本号及版本编译元数据可以加到“主版本号.次版本号.修订号”的后面,作为延伸。


go list -m all这个命令的输出,我们可以看到我们使用的是未标记版本的golang.org/x/text。现在把它升级到最新的标记的版本,并测试一下会发现能够正常使用:

F:\hello>go get golang.org/x/text
go: finding golang.org/x/text v0.3.2
go: finding golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
go: downloading golang.org/x/text v0.3.2
go: extracting golang.org/x/text v0.3.2

F:\hello>go test
PASS
ok      hello   0.161s

注意:以上这一步go get golang.org/x/text,同样需要开启代理。

哇哦!一切正常。让我们看看go list -m all

F:\hello>go list -m all
hello
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0

再看看go.mod文件:

module hello

go 1.12

require (
	golang.org/x/text v0.3.2 // indirect
	rsc.io/quote v1.5.2
)

依赖包golang.org/x/text已经升级到了最新的标记的版本(v0.3.2)。go.mod文件也同样的更新了。其中indirect表示这个依赖包不是被我们直接使用,而是其他依赖包用到。可以使用go help modules命令获取更多的信息。

现在我们尝试升级依赖包rsc.io/sampler的次版本。方法同上,先执行go get命令再执行go test:

F:\hello>go get rsc.io/sampler
go: finding rsc.io/sampler v1.99.99
go: downloading rsc.io/sampler v1.99.99
go: extracting rsc.io/sampler v1.99.99

F:\hello>go test
--- FAIL: TestHello (0.00s)
    hello_test.go:8: Hello() = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Hello, world."
FAIL
exit status 1
FAIL    hello   0.179s

哦,不!最新版本的rsc.io/sampler和我们之前用的不兼容了。让我们看看这个依赖包所有可用的标记版本:

F:\hello>go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99

我们之前用的是v1.3.0;显然v1.99.99不适用,那我们可以试试v1.3.1:

F:\hello>go get rsc.io/sampler@v1.3.1
go: finding rsc.io/sampler v1.3.1
go: downloading rsc.io/sampler v1.3.1
go: extracting rsc.io/sampler v1.3.1

F:\hello>go test
PASS
ok      hello   0.181s

注意一下go get中显式参数@v1.3.1。一般来说,每次使用go get命令都可以带上显示的版本;如果不加,默认值是@latest,将解析最新的版本。

添加另一个主版本依赖包

让我们再添加一个函数func Proverb,该函数将调用由依赖包rsc.io/quote/v3提供的quote.Concurrency。首先在hello.go中加入新函数:

package hello

import (
	"rsc.io/quote"
	quoteV3 "rsc.io/quote/v3"
)

func Hello() string {
	return quote.Hello()
}

func Proverb() string {
	return quoteV3.Concurrency()
}

然后在hello_test.go中添加测试函数:

func TestProverb(t *testing.T) {
    want := "Concurrency is not parallelism."
    if got := Proverb(); got != want {
        t.Errorf("Proverb() = %q, want %q", got, want)
    }
}

最后测试一下:

F:\hello>go test
go: finding rsc.io/quote/v3 v3.1.0
go: downloading rsc.io/quote/v3 v3.1.0
go: extracting rsc.io/quote/v3 v3.1.0
PASS
ok      hello   0.185s

现在可以看到我们的Module同时依赖rsc.io/quotersc.io/quote/v3:

F:\Users\QQT\Documents\Go Projects\NoGOPATH\hello>go list -m rsc.io/q...
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0

每一个不同的主版本(v1、v2、v3等等)对于Go Module都有不同的路径,从第二个主版本开始(v2)路径的结尾必须是主版本号。就像上面这个例子: rsc.io/quotev3不再是rsc.io/quote了,而是rsc.io/quote/v3。这种约定称为**语义导入版本控制**,它为不兼容的依赖包(具有不同版本)提供了不同的名称。相比之下,v1.6.0版本的rsc.io/quote应该向后兼容v1.5.2,因为它们都叫rsc.ip/quote。在前面的小节中,rsc.io/sampler v1.99.99按理来说应该向后兼容rsc.io/sampler v1.3.0,但是bug或错误不可避免。

Go对于一个特定路径的模块,只会构建其中一个版本。意思就是每个主要的版本都只能有一个:例如最多一个rsc.io/quote,一个rsc.io/quote/v2,一个rsc.io/quote/v3等等。这就要求开发者对于单个依赖包的路径有所要求,一个程序构建时不可能同时包含rsc.io/quote v1.5.2rsc.io/quote v1.6.0。但是允许同时存在不同主版本的依赖包,因为它们有着不同的路径。在本例中,我们要使用的quote.Concurrency来自rsc.io/quote/v3,但是还未完全脱离rsc.io/quote v1.5.2的依赖。像这种增量迁移的能力在大型的程序或代码库中显得尤其重要。

将依赖包升级到新的主版本

现在让我们完全从rsc.io/quote转移至rsc.io/quote/v3吧。因为主版本的改变,我们应该料到一些Api可能已经因为不兼容而被删除、重命名或升级。查看一下文档,我们发现Hello函数已经升级为HelloV3:

F:\hello>go doc rsc.io/quote/v3
package quote // import "rsc.io/quote/v3"

Package quote collects pithy sayings.

func Concurrency() string
func GlassV3() string
func GoV3() string
func HelloV3() string
func OptV3() string

我们可以把在hello.go中的quote.Hello()升级为quote.HelloV3():

package hello

import (
	quoteV3 "rsc.io/quote/v3"
)

func Hello() string {
	return quoteV3.HelloV3()
}

func Proverb() string {
	return quoteV3.Concurrency()
}

这时候,就不需要重命名导入依赖包了,可以把重命名删了:

package hello

import (
	"rsc.io/quote/v3"
)

func Hello() string {
	return quote.HelloV3()
}

func Proverb() string {
	return quote.Concurrency()
}

运行一下测试,确保没有错误:

F:\hello>go test
PASS
ok      hello   0.184s

删除未使用的依赖包

这时候rsc.io/quote已经没有用了,但是它仍然在go list -m all中:

F:\hello>go list -m all
hello
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1

也在go.mod文件中:

module hello

go 1.12

require (
	golang.org/x/text v0.3.2 // indirect
	rsc.io/quote v1.5.2
	rsc.io/quote/v3 v3.1.0
	rsc.io/sampler v1.3.1 // indirect
)

这是为啥呢?因为构建一个单独依赖包,就像使用go buildgo test命令时,可以很容易的判断什么时候缺少什么依赖包,什么时候需要添加,但是无法判断什么时候可以安全删除。只有在检查Module中所有的依赖包以及这些依赖包构建所需要的依赖包的标记之后,才能够删除无用的依赖包。普通的构建命令不会执行这一个步骤,因此无法删除无用的依赖包。

go mod tidy命令就是用来帮助删除这些无用的依赖包的:

F:\hello>go mod tidy

F:\hello>go list -m all
hello
golang.org/x/text v0.3.2
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
rsc.io/quote/v3 v3.1.0
rsc.io/sampler v1.3.1

再查看一下go.mod文件:

module hello

go 1.12

require (
	golang.org/x/text v0.3.2 // indirect
	rsc.io/quote/v3 v3.1.0
	rsc.io/sampler v1.3.1 // indirect
)

最后测试一下:

F:\hello>go test
PASS
ok      hello   0.169s

总结

Go Modules 是未来Go的依赖包管理工具,再目前的Go 1.11和Go 1.12中都已经支持。

以下是Go Modules的使用的基本命令:

  • go mod init 创建一个新Modules,初始化go.mod文件。
  • go build, go test 构建命令,添加所需要的依赖包,同时写入go.mod文件。
  • go list -m all 打印当前Modules的依赖包。
  • go get 更改所需依赖包的版本(或添加新的依赖包)。
  • go mod tidy 移除不需要的依赖包。

小伙伴们,把Go Modules用起来吧!

个人站点:https://www.quanquanting.com/

参考

[1]https://blog.golang.org/using-go-modules

[2]https://zhuanlan.zhihu.com/p/59687626

[3]https://semver.org/lang/zh-CN/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Go Module系列教程】手把手教你,如何使用Go Module 的相关文章

  • 导入“google/api/annotations.proto”未找到或有错误。如何将其添加为依赖项?

    按照文档如何设置 gRPC 网关 https github com grpc ecosystem grpc gateway 我发现自己陷入了生成 grpc 网关的第四步 也就是说 当添加以下行时 事情就会崩溃 import google a
  • Go TCP 读取是非阻塞的

    我正在尝试用 Go 创建服务器和客户端 我已经成功地与服务器和客户端进行通信 但我遇到的问题是golang中的TCP读取是非阻塞的 我想知道 golang 中的读取是否有可能像 C 中的读取一样阻塞 谢谢 EDIT 这是服务器的源代码 fu
  • golang - 省略 json 属性进行序列化的优雅方法

    我有一个用户结构 其中包含密码等敏感字段 type User struct UID string json uid binding required Password string json password binding require
  • Go 中带有 TTL 选项的映射

    我需要构建这样的数据结构 map string SomeType 但它必须将值存储大约 10 分钟 然后从内存中清除 第二个条件是记录数量 它必须是巨大的 该数据结构必须至少添加每秒 2 5K 条记录 那么 Go 中最正确的实现方法是什么
  • Golang导入包错误

    go 5 2 在以下任一位置找不到包 github com googollee go socket io usr local go src github com googollee go socket io 来自 GOROOT Users
  • Golang xml.Unmarshal 接口类型

    使用xml我在解组非同质类型列表时遇到问题 考虑以下 XML 文档 其嵌套元素是非同质类型的列表
  • 从私钥中提取公钥

    我尝试通过以下方式以编程方式完成步骤 2 1 openssl genrsa out signing pem 2048 2 openssl rsa in signing pem outform PEM pubout out signing p
  • 尝试创建问题时 GitHub API 422 出现意外错误响应

    当向 GitHub API V3 发布问题时 我收到了意外的响应 即422不可处理的实体 但是 错误的详细信息是针对搜索端点的 而不是针对 POST 创建端点的 message 验证失败 errors resource 搜索 field q
  • struct{} 和 struct{}{} 在 Go 中如何工作?

    我想知道 Go 中的 struct 和 struct 是什么意思 示例如下 array index struct or make map type struct struct is a keyword https golang org re
  • Go中的切片分配是否复制内存

    目的 我有一个大缓冲区 我想要一个指向缓冲区中不同位置的指针数组 切片 我在做什么 datPtrs make byte n for i 0 i
  • 在 docker build 中缓存“go get”

    我想将 golang 单元测试封装在 docker compose 脚本中 因为它依赖于多个外部服务 我的应用程序有很多依赖项 因此需要一段时间go get 如何以允许构建 docker 容器的方式缓存包 而无需每次要测试时下载所有依赖项
  • 如何用 Go 将多个字符串解析为模板?

    有没有像这样的简单方法template ParseFiles base html home html 但是对于字符串来说 如何从一组字符串构建模板 我有一个基本模板和一个页面模板列表 全部为字符串 我想在基本模板之上构建它们 我想出了如何合
  • 按顺序范围循环映射

    我正在寻找一种确定的方法来范围Go map为了 Go 规范 https golang org ref spec For statements陈述如下 映射的迭代顺序未指定 并且不保证从一次迭代到下一次迭代的顺序相同 如果在迭代过程中删除尚未
  • 如何更新任意go结构的所有字符串字段?

    我尝试编写一个函数来更新所有字符串字段随意的结构体 像这样 type Student struct Name string Age int func SetStringField obj interface reflect ValueOf
  • 如何访问 Go 中的嵌套模块(子模块)?

    去版本 1 12 9 这是一个简单演示项目的结构 所以我们有一个模块domain 其中包含两个模块 activity and person 我想将域与主文件中的所有嵌套模块一起使用 gt 模块 go 我知道如何导入domain主要在go m
  • 如何在Go中从interface{}解组到interface{}

    我的系统中有多个通过 RPC 进行通信的节点 我正在尝试通过 RPC 将 map string interface 发送到另一个节点 发送方使用 json Marshal 接收方使用 json Unmarshal 来获取地图 假设在发送方
  • go:找到模块但不包含包

    我正在尝试安装 go 的网络包 但收到 不包含包错误 终端截图 我咨询过 go 模块 latest 已找到但不包含包 https stackoverflow com questions 62974985 go module latest f
  • Golang 中的“相互”包导入

    是否可以在 Golang 中执行 相互 包导入之类的操作 举例来说 我有两个包 A 和 B 分别具有 AFunc 和 BFunc BFunc2 函数 package A import B func AFunc do stuff but al
  • 如何检查我的 golang 应用程序是否使用 Boringcrypto 而不是本机 golang crypto?

    上下文 我正在阅读多篇有关使我的 golang 应用程序符合 FIPS 要求的文章 换句话说 使我的应用程序使用 Boringcrypto 而不是本机 golang crypto https kupczynski info posts fi
  • golang:使用 gin 路由器服务 net.Conn

    我有一个处理传入 TCP 连接的函数 func Handle conn net Conn error 另外 我有一个初始化的 gin 路由器 带有已实现的句柄 router gin New router GET router POST Th

随机推荐

  • uml交互图

    交互图用来描述系统中的对象是如何进行相互作用的 即一组对象是如何进行消息传递的 当交互图建模时 通常既包括对象 每个对象都扮演某一特定的角色 又包括消息 每个消息都代表对象之间的通信活动 并导致一定的动作发生 关键字 对象 顺序 消息 顺序
  • 7.13字节跳动模拟面试

    GDB调试常见命令 进入GDB 取消联系 插入端点 gdb help 查看命令帮助 具体命令查询在gdb中输入help 命令 简写h gdb run 重新开始运行文件 run text 加载文本文件 run bin 加载二进制文件 简写r
  • 【TODO】2023年秋招笔试未竞

    2023年秋招笔试没做完的题 腾讯20230326笔试三道 米哈游20230813笔试第三题 网易雷火0820第2 3 4题 第三题 深信服0912B卷3 4题 第三题 背包装满最小数量 第四题 腾讯0915重考最后一道 字节0917秋招第
  • 5.xaml RadioButton按钮

    1 运行图 2 运行源码 a Xaml源码
  • 基于面部视觉的疲劳检测-哈欠

    基于视觉的疲劳检测可以认为大致分为三个部分 点头 哈欠 眨眼 分别为姿态 嘴部特征 眼部特征 本文主要介绍哈欠的测定方法 首先研究了陈博士 基于可拓学与面部视觉 一文 他提出一种基于特征点曲线拟合的嘴唇内轮廓检测方法 先对嘴巴进行粗定位 然
  • Removable singularity

    In complex analysis a removable singularity of a holomorphic function is a point at which the function is undefined but
  • darknet 网络构建过程

    整个网络的构建从load network cfgfile weightfile clear 函数开始 从cfg文件中读取网络配置文件 分配好内存 加载预训练好的权重 network load network char cfg char we
  • Spring工作原理

    Spring工作原理 Spring框架是由于软件开发的复杂性而创建的 Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情 然而 Spring的用途不仅仅限于服务器端的开发 从简单性 可测试性和松耦合性角度而言 绝大
  • Sass -- 变量、计算、导入

    变量 在Sass中 支持使用变量 变量以 开头 变量使用 Sass不存在变量提升 变量必须先定义再使用 如果需要将变量在字符串中使用 需将变量写在 中 计算 在Sass中 允许数值运算 导入 Sass 类似 CSS 支持 import 指令
  • linux开放端口命令

    linux系统中控制端口的开启与关闭可以由命令来执行 下面由学习啦小编为大家整理了linux下开放端口命令的相关知识 希望对大家有所帮助 linux开放端口命令1 打开指定端口 sbin iptables I INPUT p tcp dpo
  • PyQt5 主窗口操作多个子窗口实现

    实现思路 1 pyqt5 designer 生成ui py 修改文件 2 ui py 主py 直接操作 3 main py 操作 ui 继承类py ui py 优选方案3 示例 from main win import Ui MainWin
  • 客户端session与服务端session

    转自 https www cnblogs com qhyhao p 3565681 html 会话 Session 跟踪是Web程序中常用的技术 用来跟踪用户的整个会话 常用的会话跟踪技术是Cookie与Session Cookie通过在客
  • 移动互联网应用程序必要个人信息范围

    常见类型App的必要个人信息范围 必要个人信息 是指保障APP基本功能服务正常运行所必需的个人信息 缺少该信息APP即无法实现基本功能服务 具体是指消费侧用户个人信息 不包括服务供给侧用户个人信息 地图导航类 基本功能服务为 定位和导航 必
  • Unity3D Linear01Depth & LinearEyeDepth d3d

    Unity3D Linear01Depth LinearEyeDepth 函数深度解析 原创 2015年07月11日 20 25 42 5609 UnityCG cginc中原函数如下 Z buffer to linear 0 1 dept
  • Java学习(110)Java输入输出流——文件输入流FileInputStream

    Java输入输出流 文件输入流FileInputStream FileInputStream概述 1 FileInputStream作用 2 FileInputStream的常用方法简介 FileInputStream案例 前置条件 rea
  • matlab程序打包成软件(exe可执行文件)

    文章目录 下载matlab runtime 打包 分享安装 下载matlab runtime 略 打包 分享安装 打包生成的文件夹如下 包含runtime的exe文件 安装后即可在没有matlab环境下运行
  • 使用免费的Spire.Pdf.dll打印无水印的PDF文件

    文章目录 前言 一 如何获取免费的无水印的Spire Pdf dll 二 使用步骤 1 引入库 2 打印 总结 前言 最近想利用c 打印PDF文件 在网上找了各种办法 发现最简单的就是使用第三方的动态链接库Spire Pdf dll了 但是
  • Spring的第一个入门程序(学习总结)

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 提示 以下是本篇文章正文内容 下面案例可供参考 一 Spring框架的概述 1 1 1 Spring是什么 Spring是分层的 Java SE EE应用full stack
  • CHIP-2020 中文医学文本实体关系抽取

    来源 这里 这个项目的本质是 医学文本的实体关系联合抽取问题 既要解决命名实体识别 又要解决关系分类问题 使用RoFormerV2模型作为预训练模型 GPLinker作为下游模型 在Embedding层添加FGM对抗训练增加模型性能 一 数
  • 【Go Module系列教程】手把手教你,如何使用Go Module

    Go Module系列教程 手把手教你如何使用Go Module 请先看我 看了网上的好多中文博客 一直都没有看懂 这个Go Module 到底如何使用 无奈 只能去看看官方的教程是怎么样的了 本文结合 官方文档 和 我自己的实践 根据官方