英文:
Cross compile net/http for distribution
问题
我已经在一个 Docker 容器中构建了以下代码,使用了以下架构:
cat /proc/version
Linux version 3.16.7-tinycore64 (root@064f0e1ce709) (gcc version 4.7.2 (Debian 4.7.2-5)) #1 SMP Tue Dec 16 23:03:39 UTC 2014
package main
import "fmt"
func main() {
fmt.Println("Hello")
}
这个二进制分发版本在一个 busybox 容器上运行没有问题,使用了相同的架构,而且没有安装 golang。
问题是,当我对以下代码做同样的操作时:
package main
import (
"fmt"
"net/http"
)
const (
port = ":80"
)
var calls = 0
func HelloWorld(w http.ResponseWriter, r *http.Request) {
calls++
fmt.Fprintf(w, "Hello, world! You have called me %d times.\n", calls)
}
func init() {
fmt.Printf("Started server at http://localhost%v.\n", port)
http.HandleFunc("/", HelloWorld)
http.ListenAndServe(port, nil)
}
func main() {}
然后我得到了以下错误信息:
ash: ./hello_world: not found
我可能缺少一些依赖项,比如 "net/http"?但是我以为 go build 会将所有依赖项都编译到二进制文件中。这对于 go build 和 go install 都是如此。
有什么想法吗?
英文:
I have build the following code in a docker container with the following architecture:<br>
cat /proc/version
Linux version 3.16.7-tinycore64 (root@064f0e1ce709) (gcc version 4.7.2 (Debian 4.7.2-5) ) #1 SMP Tue Dec 16 23:03:39 UTC 2014
package main
import "fmt"
func main() {
fmt.Println("Hello")
}
The binary distributed, runs with no problem on a busybox container, with the same architecture without installing golang.<br>
<br>
The problem
When I do the same for the following code:<br>
package main
import (
"fmt"
"net/http"
)
const (
port = ":80"
)
var calls = 0
func HelloWorld(w http.ResponseWriter, r *http.Request) {
calls++
fmt.Fprintf(w, "Hello, world! You have called me %d times.\n", calls)
}
func init() {
fmt.Printf("Started server at http://localhost%v.\n", port)
http.HandleFunc("/", HelloWorld)
http.ListenAndServe(port, nil)
}
func main() {}
Then I get:<br>
ash: ./hello_world: not found <br>
I might be missing some dependencies - like "net/http"?<br>
But I thought the go build would build all into the binaries.<br>
This is for both go build & go install.
Any idea?
答案1
得分: 1
答案很可能是这篇文章中描述的那个。
> 标准库的一些关键部分使用了CGO[...]如果你将Go交叉编译到Darwin或Linux,你的程序将不会使用系统的DNS解析器。它们也不能使用本机主机证书存储。它们也不能查找用户的主目录。
而CGO默认会动态链接到一些标准系统接口。
该文章建议使用gonative来解决这个问题。如果那不是你的菜,有些人建议使用:
go build -ldflags "-linkmode external -extldflags -static"
还可以阅读:https://groups.google.com/d/topic/golang-nuts/H-NTwhQVp-8/discussion
英文:
The answer is most probably the one described in this article.
> Some critical parts of the standard library use CGO [...] if you cross-compile Go to Darwin or Linux your programs won’t use the system DNS resolver. They also can’t use the native host certificate store. They also can’t look up the user’s home directory, either.
And CGO links against some standard system interfaces by default, dynamically.
The article suggests using gonative to fix the problem. If that's not your cup of tea, some people suggest using:
go build -ldflags "-linkmode external -extldflags -static"
Also read: https://groups.google.com/d/topic/golang-nuts/H-NTwhQVp-8/discussion
答案2
得分: 1
我认为你需要禁用cgo并使用netgo
标志进行构建:
> 默认情况下,net包需要cgo,因为主机操作系统通常需要介入网络调用设置。但在某些系统上,可以在没有cgo的情况下使用网络,并且这样做是有用的,例如避免动态链接。新的构建标签netgo(默认情况下关闭)允许在可能的系统上使用纯Go构建net包。
netgo
标签要求版本为1.2及以上。
英文:
I think you need to disable cgo and build with netgo
flag :
> The net package requires cgo by default because the host operating
> system must in general mediate network call setup. On some systems,
> though, it is possible to use the network without cgo, and useful to
> do so, for instance to avoid dynamic linking. The new build tag netgo
> (off by default) allows the construction of a net package in pure Go
> on those systems where it is possible.
The netgo
tag requires version 1.2 and above.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论