Golang中同时使用go modules和自定义go包时遇到的问题
Golang中同时使用go modules和自定义go包时遇到的问题 大家好,我目前正在开发一个使用 client-go 库(用于 Kubernetes)的项目,我的代码已经准备好了,但我想正确地修改代码,以便将使用 client-go 和 K8s API 的函数放在一个包下。我尝试使用自定义包来实现它。
Golang 版本:go version go1.16.4 linux/amd64 由于此版本默认启用了 go modules,所以我使用 GO111MODULE=off go run main.go
目前我的工作目录结构大致如下: |-WorkingDirectory |–main.go |–go.mod |–go.sum 在这种情况下,main.go 运行完全正常,我必须使用 go run main.go(因为如果我在此情况下使用 GO111MODULE=off go run main.go,则会抛出错误:cannot find package k8s.io/client-go/tools/clientcmd)
由于我希望将所有 client-go 函数放在一个包中,我尝试实现了以下文件结构: |-WorkingDirectory |–main.go |–test(包名) |—go.mod |—go.sum |—test1.go
但在这种情况下,我遇到了困难。 如果我使用 go run main.go,由于我使用的是 go1.16.4,我可以使用自定义包;而如果我使用 GO111MODULE=off go run main.go,我可以享受使用自定义包的便利,但 client-go 和 Kubernetes API 将无法工作,因为我为它们使用了 go.mod。
所以,请问有人能帮我摆脱这个困境,并指导我如何创建一个包含所有使用 client-go 和 Kubernetes API 函数的自定义包吗?
更多关于Golang中同时使用go modules和自定义go包时遇到的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
为什么你使用嵌套模块而不是仅仅使用嵌套包(没有它自己的 go.mod)?
更多关于Golang中同时使用go modules和自定义go包时遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
@skillian 能否请你解释一下。如果你能告诉我文件结构会是什么样子,那就太好了。
我认为是这样的。模块是一组一起进行版本控制的包,因此你的工作目录是一个包,你的测试文件夹也是一个包,但由于你在工作目录中有一个 go.mod 文件,它们共同构成了一个以该目录为根的模块。我自己编写模块时就是这样做的。
我认为你的文件夹结构看起来没问题。我无法完全看清哪些文件嵌套在哪里,因为你的ASCII字符画文件夹结构被论坛格式化了。尝试将应该以等宽字体显示的代码和文本用三个反引号(```)包裹起来,例如:
code/text here
我的意思是,go.mod 和 go.sum 文件应该放在顶层,而不是嵌套在你的测试包中。
是的,实际上我已经解决了这个问题。在这种情况下,我们必须使用 Go 模块,为此我们应该采用以下文件结构:
|-WorkingDirectory
|--main.go
|--go.mod
|--go.sum
|--test(the module name)
|---test1.go
|---go.mod
|---go.sum
测试模块内部的 go.mod 文件将包含测试模块内部函数所需的模块,而测试模块外部的 go.mod 文件将引用我们的测试模块。 参考链接- https://golang.org/doc/tutorial/create-module https://golang.org/doc/tutorial/call-module-code
感谢您的帮助
好的,抱歉,请看,这就是我之前提到的文件结构。
|-WorkingDirectory
|--main.go
|--test(the package name)
|---go.mod
|---go.sum
|---test1.go
我的意思是,
go.mod和go.sum文件应该放在顶层目录,而不是嵌套在你的测试包里面。
那么,你认为结构应该是这样的吗?
|-WorkingDirectory
|--main.go
|--go.mod
|--go.sum
|--test(the package name)
|---test1.go
但是我的 test1.go 也使用了一些模块,比如 K8s API 和 client-go 库,这些在 go.mod 中都有提及,这就是为什么我把 go.mod 和 go.sum 放在我的测试包里面。
这种新的文件结构能满足我的需求吗?
在 Go 1.16 中,当启用 Go Modules 时,自定义包的正确使用方式是在同一个模块内组织代码。你的问题在于将自定义包 test 放在了独立的 go.mod 文件中,这会导致模块分离,从而无法在 main.go 中正确引用。
以下是解决方案:
1. 调整项目结构
将项目结构改为标准的 Go Modules 布局,所有包共享同一个 go.mod 文件:
WorkingDirectory/
├── go.mod
├── go.sum
├── main.go
└── pkg/
└── k8sclient/
└── client.go # 你的自定义包
2. 创建自定义包
在 pkg/k8sclient/client.go 中定义你的 client-go 功能:
package k8sclient
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/rest"
)
func NewClient(kubeconfig string) (*kubernetes.Clientset, error) {
var config *rest.Config
var err error
if kubeconfig == "" {
config, err = rest.InClusterConfig()
} else {
config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
}
if err != nil {
return nil, err
}
return kubernetes.NewForConfig(config)
}
func GetPods(client *kubernetes.Clientset, namespace string) ([]string, error) {
pods, err := client.CoreV1().Pods(namespace).List(context.Background(), metav1.ListOptions{})
if err != nil {
return nil, err
}
podNames := make([]string, 0, len(pods.Items))
for _, pod := range pods.Items {
podNames = append(podNames, pod.Name)
}
return podNames, nil
}
3. 在 main.go 中使用自定义包
package main
import (
"fmt"
"log"
"your-module-name/pkg/k8sclient" // 替换为你的模块名
)
func main() {
client, err := k8sclient.NewClient("")
if err != nil {
log.Fatal(err)
}
pods, err := k8sclient.GetPods(client, "default")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Pods in default namespace: %v\n", pods)
}
4. 确保 go.mod 正确配置
你的 go.mod 文件应该类似这样:
module your-module-name
go 1.16
require (
k8s.io/client-go v0.21.0
// 其他依赖...
)
5. 运行程序
现在你可以直接使用以下命令运行:
go run main.go
或者构建后运行:
go build -o myapp
./myapp
关键点说明:
- 不要使用
GO111MODULE=off,Go 1.16 默认启用 modules - 所有包应该在同一个模块内
- 自定义包的导入路径基于模块名 + 包相对路径
- 确保
go.mod中包含了 client-go 的依赖
这种结构允许你在同一个模块内组织代码,同时能够正确管理 client-go 的依赖。

