我想以二进制形式分发包而不包含源代码。
我的演示项目目录结构如下:
demo
├── greet
│ ├── greet.go
│ └── hi
│ └── hi.go
├── hello
│ └── hello.go
└── main.go
main.go:
package main
import (
"fmt"
"demo/greet"
"demo/hello"
)
func main(){
fmt.Println("greet:")
greet.Greet()
fmt.Println("hello:")
hello.Hello()
}
greet.go
package greet
import (
"demo/greet/hi"
"fmt"
)
func Greet(){
fmt.Println("Greet Call Hi")
hi.Hi()
}
hi.go
package hi
import "fmt"
func Hi(){
fmt.Println("Hi")
}
hello.go
package hello
import (
"fmt"
"demo/greet"
)
func Hello(){
fmt.Println("hello call greet")
greet.Greet()
}
我这样做:
[user@localhost greet]$ go install -a ./...
它在$ GOPATH / pkg / linux_amd64 / demo中生成了greet.a和greet / hi.a. 然后我编辑hi.go和greet.go。
[user@localhost greet]$ cat greet.go
//go:binary-only-package
package greet
[user@localhost greet]$ cat hi/hi.go
//go:binary-only-package
package hi
然后我运行main.go,我收到错误:
[user@localhost greet]$ cat hi/hi.go
# command-line-arguments
cannot find package demo/greet/hi (using -importcfg)
/home/user/go/pkg/tool/linux_amd64/link: cannot open file : open : no such file or directory
greet 是我要分发的包。如果我删除包 hi ,则main.go可以正常运行。
demo
├── greet
│ └── greet.go
├── hello
│ └── hello.go
└── main.go
安装:
[user@localhost greet]$ go install .
[user@localhost greet]$ vim greet.go
//go:binary-only-package
package greet
[user@localhost greet]$ cd ..
[user@localhost demo]$ go run main.go
greet:
Greet ...
hello:
hello call greet
Greet ...
[user@localhost demo]$
//go:binary-only-package
方法可以很好地工作)请帮助或尝试提出一些解决方法。提前谢谢。
答案 0 :(得分:1)
注意(2019):仅二进制软件包不再受支持。
Go 1.12 (February 2019) release notes之后(CL 152918之后):
仅二进制包
Go 1.12是最后一个支持纯二进制软件包的版本。
这在Go issue 28152中有详细说明:
仅二进制软件包越来越难以安全地支持。
不能保证仅二进制程序包的编译所使用的依赖版本与最终链接所使用的依赖版本相同(并且坚持这样做可能会很麻烦)。
结果,可能已经使用转义分析结果或内联函数主体来编译仅二进制包,以解决不再准确的依赖项。
结果可能是无声的内存损坏。我的记忆是,我们最初添加了仅二进制软件包,以便教授可以分发二进制解集,以便未完成实验2的学生仍可以继续进行实验3。
我不知道为什么还有其他人会使用它们,但是随着编译器变得越来越复杂,它们可能会越来越被破坏。
答案 1 :(得分:0)
“go run”将编译并运行给定的主包。因此它会检查源文件的时间戳,如果它们看起来比以前编译的库(.a文件)更新,则重新编译它们。
对于仅二进制包,它将跳过此步骤。因此,在这种情况下,它将检查任何给定的包,只有一个源文件,文本为// go:binary-only-package。这就是指定功能的方式。当它看到它时,它将只使用.a文件。
如果你有一个包含源文件的子包,那么它们中的文件似乎最终会作为封闭根包的一部分计算,并且只有一个源文件的要求被破坏。那么“go run”就会失败。我怀疑这就是为什么它不起作用。这就是为什么删除hi子包会导致它工作。
二进制文件的预期用例是您编译包,然后当您将其提供给其他人时,您不包含任何源文件,只包含.a文件。但要实现这一点,您需要能够告诉其他人的编译器您的包只是.a文件。为此,您需要只包含一个源文件和文本// go:binary-only-package。你基本上已经在这里看到,对于一个有子包的包,整个东西必须只有一个这样的源文件,只能有一个,你不能在子包文件夹中有更多。所以只提供一个。这就是该功能的工作原理。您将.a文件和一个源文件提供给其他人。