title: When using CGO_ENABLED is must and what happens
body: <h1>Question</h1>
  
  <p>Please help understand when <strong>CGO_ENABLED</strong> is must and unavoidable, and what happens with the go compilation process.</p>
  
  <h2>When CGO_ENABLED is must</h2>
  
  <p>After having read the articles in <strong>references</strong>, it looks as far as go has cross-compile native support for the target platform, <strong>CGO_ENABLED</strong> will never be a must. Is this correct?</p>
  
  <p>The situation when <strong>cgo</strong> and <strong>CGO_ENABLED</strong> is absolute-must is when go compiler cannot produce the binary code for the target platform. For instance, imagine I am writing a Space X control board embedded program in Go and I have to use C library and the compiler for the board. There is no other library or compiler available for the board.</p>
  
  <p>In such case, I have to do <strong>CGO_ENABLED=1</strong> and tell <strong>cgo</strong> the compiler and the linker to use and where the C library binaries are copied in my laptop, and setup the compilers CFLAGS etc etc. Perhaps I would have to use C for all the coding instead of using Go in this case, but somehow I was in the situation that I had to use Go. This is when <strong>CGO_ENABLED=1</strong> would be must. Is this correct?</p>
  
  <p>Otherwise, if especially go has the support for the target platform cross-compilation, using <strong>CGO_ENABLED=1</strong> could be a short-cut to just re-use the existing C library for the target platform. Is this correct or is there any other reason why <strong>CGO_ENABLED</strong> is required?</p>
  
  <h2>What happens</h2>
  
  <p>I suppose when <strong>CGO_ENABLED=1</strong> is used, basically there will be a composition of the binary from Go part, and the binary from the C library in the executable created by <strong>go build</strong> command. And at runtime, the execution goes back and forth between the two binary world of go and C. Go binary side would not know C side, so the go tools like debugger would not be available. </p>
  
  <p>I suppose whether the executable hard-links all the libraries or uses dynamic linking depends on the target platform compiler. </p>
  
  <p>Are these correct understandings?</p>
  
  <p>The reason <strong>CGO_ENABLED=0</strong> by default for cross-compilation is because we should use the go built-in support of the target platform cross-compilation and there should be no reason not to do so.</p>
  
  <p>The reason <strong>CGO_ENABLED=1</strong> by default for the native local platform is because the cgo compiler knows (or the author of the compiler knows) the local machine architecture and the OS libraries (or well known 3rd party's) available, hence best-optimization can be expected? But I am not sure this is true because the go compiler itself can be best-optimized for the local OS and architecture, then why need to use cgo? </p>
  
  <p>Kindly explain why <strong>CGO_ENABLED=1</strong> by default for the native local platform.</p>
  
  <h1>References</h1>
  
  <ul>
  <li><p><a href="https://dave.cheney.net/tag/cgo" rel="noreferrer">cgo is not Go</a></p>
  
  <blockquote>
    <p>Some people, when confronted with a problem, think “I know, I’ll use cgo.” Now they have two problems.<br/><br/>
    cgo is an amazing technology which allows Go programs to interoperate with C libraries. It’s a tremendously useful feature without which Go would not be in the position it is today. cgo is key to ability to run Go programs on Android and iOS.<br/><br/>
    However, and to be clear these are my opinions, I am not speaking for anyone else, I think cgo is overused in Go projects. I believe that when faced with reimplementing a large piece of C code in Go, programmers choose instead to use cgo to wrap the library, believing that it is a more tractable problem. I believe this is a false economy.<br/><br/>
    Obviously, there are some cases where cgo is unavoidable, most notably where you have to interoperate with a graphics driver or windowing system that is only available as a binary blob. But those cases where cgo’s use justifies its trade-offs are fewer and further between than many are prepared to admit.<br/><br/>
    Go’s support for cross compilation is best in class. As of Go 1.5 you can cross compile from any supported platform to any other platform with the official installer available on the Go project website.<br/><br/>
    By default cgo is disabled when cross compiling. Normally this isn’t a problem if your project is pure Go. When you mix in dependencies on C libraries, you either have to give up the option to cross compile your product, or you have to invest time in finding and maintaining cross compilation C toolchains for all your targets.<br/><br/>
    The number of platforms that Go supports continues to grow. Go 1.5 added support for 64 bit ARM and PowerPC. Go 1.6 adds support for 64 bit MIPS, and IBM’s s390 architecture is touted for Go 1.7. RISC-V is in the pipeline. If your product relies on a C library, not only do you have the all problems of cross compilation described above, you also have to make sure the C code you depend on works reliably on the new platforms Go is supporting — and you have to do that with the limited debuggability a C/Go hybrid affords you. Which brings me to my next point.</p>
  </blockquote></li>
  <li><p><a href="https://stackoverflow.com/questions/54456100/why-does-cgo-enable-make-a-such-impact-on-virtual-memory">Why does CGO_ENABLE make a such impact on virtual memory?</a></p>
  
  <blockquote>
    <p>the compiler of the "reference" Go implementation (historically dubbed "gc"; that one, available for download from the main site) by default produces statically-linked binaries. This means, such binaries rely only on the so-called "system calls" provided by the OS kernel and do not depend on any shared libraries provided by the OS (or 3rd parties).<br/><br/>
    On Linux-based platforms, this is not completely true: in the default setting (building on Linux for Linux, i.e., not cross-compiling) the generated binary is actually linked with libc and with libpthread (indirectly, via libc).</p>
  </blockquote></li>
  <li><p><a href="https://go-review.googlesource.com/c/go/+/12603/2/src/cmd/cgo/doc.go" rel="noreferrer">cmd/cgo: document how CGO_ENABLED works today</a></p>
  
  <blockquote>
    <p>The cgo tool is enabled by default for native builds on systems where
    it is expected to work.  It is disabled by default when
    cross-compiling.  You can control this by setting the CGO_ENABLED
    environment variable when running the go tool: set it to 1 to enable
    the use of cgo, and to 0 to disable it.  The go tool will set the
    build constraint "cgo" if cgo is enabled.<br/><br/>
    When cross-compiling, you must specify a C cross-compiler for cgo to
    use.  You can do this by setting the CC_FOR_TARGET environment
    variable when building the toolchain using make.bash, or by setting
    the CC environment variable any time you run the go tool.  The
    CXX_FOR_TARGET and CXX environment variables work in a similar way for
    C++ code.</p>
  </blockquote></li>
  <li><p><a href="https://blog.golang.org/cgo" rel="noreferrer">C? Go? Cgo!</a></p></li>
  <li><a href="https://golang.org/cmd/cgo/" rel="noreferrer">cgo</a></li>
  </ul>