Go语言是否依赖于C运行时?

huangapple go评论85阅读模式
英文:

Does Go depend on C runtime?

问题

我可以帮你翻译。以下是你要翻译的内容:

我找不到关于Go语言是否依赖于C运行时的信息。如果它依赖于C运行时,是否会将其静态编译到二进制文件中,以便使用Go编写的应用程序在没有依赖的情况下在任何地方运行?

这里有一个关于C运行时库的主题:什么是C运行时库

英文:

I can't find info does Go depend on C runtime? If it depends on it, is it statically compiled into the binary to make the application written in Go work everywhere without dependencies?

Here is the topic about what C runtime is

答案1

得分: 20

如果你在谈论由Go编译器提供的可执行文件,那么答案是“是或否,这取决于情况”:

在大多数情况下,生成的可执行程序*不依赖于C运行时库。

然而,在某些平台和特定情况下,C运行时库会被动态链接进来。
特别是在Linux上使用Go版本<1.5时,当使用DNS解析时,运行时依赖于平台的libc实现来处理此类解析。
在1.5中,这已经进行了重构

另一个可能的情况是(如果我没记错的话)Solaris,它没有稳定的方式直接访问内核的系统调用,需要通过平台的libc来路由这些调用

还有另一种情况:使用cgo,它是一个用于将Go代码与外部C代码进行接口的层。使用cgo会使你的Go程序依赖于C运行时库。请注意,你可能不直接使用cgo,但你使用的一个或多个第三方包可能使用了cgo,从而使你的程序间接依赖于C运行时库。

英文:

If you're talking about executable files provided by a Go compiler, then the answer is "yes or no&mdash;it depends":

In most cases, the resulting executable program does not depend on a C run-time library.

However, on some platforms under certain circumstances the C runtime library gets dynamically linked in.
In particular, this was the case with Go versions < 1.5 on Linux when DNS resolution was used: the runtime depended on the platform's libc implementation to handle such resolution.
In 1.5 this has been reworked.

Another possible case is (IIRC) Solaris which provides no stable way to access the kernel's syscalls directly and requires routing these calls through the platform's libc.

There is another case: using cgo which is a layer to interface Go code with foreign C code. Using cgo makes your Go program depend on the C runtime. Note that you might not use cgo directly but one or more of the third-party packages you might be using can use cgo, and&mdash;transitively&mdash;your program ends up depending on the C runtime library.

答案2

得分: 7

我认为接受的答案是正确的,但是一个导入了"net"包的二进制文件通常在go 1.10和Unix中仍然依赖于C运行时。

以下是一个简单回显服务器的示例代码:

package main

import (
    "io"
    "log"
    "net"
)

func main() {
    ln, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal(err)
    }

    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Print(err)
            continue
        }

        _, err = io.Copy(conn, conn) // 阻塞直到客户端关闭连接
        if err != nil {
            log.Print(err)
            continue
        }

        if err = conn.Close(); err != nil {
            log.Print(err)
        }
    }
}

构建并检查其依赖项:

$ go build ./libc_check.go
$ ldd ./libc_check
    linux-vdso.so.1 =>  (0x00007ffe34fc1000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc005d4e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc005984000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fc005f6b000)

这是因为根据发布说明,"如何运行解析器的决策是在运行时而不是构建时进行的"。

为了避免这种依赖关系,可以使用"netgo"构建标签,像这样:

$ go build -tags netgo ./libc_check.go
$ ldd ./libc_check
    not a dynamic executable
英文:

I think the accepted answer is correct, but a binary which imports the 'net' package usually depends on a c runtime even in go 1.10 and Unix.

Here is the example of the simple echo server:

package main

import (
        &quot;io&quot;
        &quot;log&quot;
        &quot;net&quot;
)

func main() {
        ln, err := net.Listen(&quot;tcp&quot;, &quot;:8080&quot;)
        if err != nil {
                log.Fatal(err)
        }

        for {
                conn, err := ln.Accept()
                if err != nil {
                        log.Print(err)
                        continue
                }

                _, err = io.Copy(conn, conn) // blocked until the client closes the conn.
                if err != nil {
                        log.Print(err)
                        continue
                }

                if err = conn.Close(); err != nil {
                        log.Print(err)
                }
        }
}

Build it and check its dependencies:

$ go build ./libc_check.go
$ ldd ./libc_check
        linux-vdso.so.1 =&gt;  (0x00007ffe34fc1000)
        libpthread.so.0 =&gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc005d4e000)
        libc.so.6 =&gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc005984000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fc005f6b000)

It is because 'the decision of how to run the resolver applies at run time, not build time' as the release note indicates.

To avoid this dependency, use the 'netgo' build tag like this:

$ go build -tags netgo ./libc_check.go
$ ldd ./libc_check
    not a dynamic executable

答案3

得分: 0

如果你指的是LibC,Go语言并不依赖它。Go语言有自己的标准库,其中包含了常用函数的实现,例如文件I/O、网络和内存管理,因此它不依赖于libc或任何其他外部库。

英文:

If you mean LibC, Go does not depend on it. Go has its own standard library that includes implementations of commonly used functions such as file I/O, networking, and memory management, so it does not rely on libc or any other external library.

huangapple
  • 本文由 发表于 2017年1月18日 20:59:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/41720090.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定