Go - Faq (资深Gopher必读)

AI 摘要: Go is a programming language designed for simplicity, speed of compilation, orthogonality of concepts, and support for concurrency and garbage collection. It does not have certain features like exceptions and generics. Go follows the CSP (Communicating Sequential Processes) model of concurrency and uses goroutines as lightweight threads. It also implements resizable, bounded stacks for efficient memory usage. Map operations in Go are not atomic and can cause concurrency issues if not handled properly. The language and libraries are protected by a compatibility promise, ensuring backward compatibility for future releases. Go is widely used at Google.

参考: https://go.dev/doc/faq

1. Usage

  1. SRE: https://go.dev/talks/2013/go-sreops.slide#17
  2. Using Go Company: https://github.com/golang/go/wiki/GoUsers
  3. Go link with C/C++
    1. It is possible to use C and Go together in the same address space, but it is not a natural fit and can require special interface software. linking C with Go code gives up the memory safety and stack management properties that Go provides. Sometimes it’s absolutely necessary to use C libraries to solve a problem, but doing so always introduces an element of risk not present with pure Go code, so do so with care.
    2. If you do need to use C with Go, how to proceed depends on the Go compiler implementation. There are three Go compiler implementations supported by the Go team. These are **gc**, the default compiler, **gccgo**, which uses the GCC back end, and a somewhat less mature **gollvm**, which uses the LLVM infrastructure.
    3. The [cgo](https://go.dev/cmd/cgo/) program provides the mechanism for a “foreign function interface” to allow safe calling of C libraries from Go code. SWIG extends this capability to C++ libraries. Gcuses a different calling convention and linker from C and therefore cannot be called directly from C programs, or vice versa.
  4. protocol buffers:
    1. https://github.com/golang/protobuf

2. Design

  1. runtime 运行时
    1. Go does have an extensive library, called the $runtime$, that is part of every Go program. The runtime library implements garbage collection, concurrency, stack management, and other critical features of the Go language
    2. It is important to understand, however, that Go’s runtime does not include a virtual machine, such as is provided by the Java runtime. Go programs are compiled ahead of time to native machine code (or JavaScript or WebAssembly, for some variant implementations). Thus, although the term is often used to describe the virtual environment in which a program runs, in Go the word “runtime” is just the name given to the library providing critical language services.
  2. Unicode 标识符
  3. 没有 X 特性 Go 的设计着眼于编程的便利性、编译的速度、概念的正交性以及支持并发和垃圾收集等特性的需求
  4. 范型特性(generic type)
    1. 1.18版本加入,多态或范型编程: https://go.dev/ref/spec#Type_parameter_declarations
    2. 一开始聚焦可伸缩性、可读性和并发性,多态编程起初被排除在外(优先级)。泛型很方便,但它们的代价是类型系统和运行时的复杂性。开发一种我们认为赋予与复杂性成比例的价值的设计需要一段时间。
  5. Go 异常处理
    1. 没有 try-catch-finally,会导致代码复杂,会鼓励程序员将普通错误定位异常
  6. CSP 并发思想
    1. 多线程难点: mutexes, condition variables, and memory barriers(内存屏障)
    2. One of the most successful models for providing high-level linguistic support for concurrency comes from $Hoare's$ Communicating Sequential Processes, or CSP. Occam and Erlang are two well known languages that stem from CSP.
    3. Go’s concurrency primitives derive from a different part of the family tree whose main contribution is the powerful notion of $channels$ as first class objects.
  7. Goroutines 替代 线程 (资源开销考虑)
    1. Goroutines are part of making concurrency easy to use.
    2. The idea, which has been around for a while, is to multiplex independently executing functions—coroutines—onto a set of threads(将独立执行的函数(协程)复用于一组线程上执行) ,
    3. When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won’t be blocked. (若一个协程发生了系统调用产生了阻塞,那么运行时会自动将这个阻塞线程上的其他协程调度到其他不同的可以运行的线程上执行,以便不会阻塞)
    4. The programmer sees none of this, which is the point. The result, which we call goroutines, can be very cheap: they have little overhead beyond the memory for the stack, which is just a few kilobytes. (仅仅是堆栈的内存几 KB 开销)
    5. To make the stacks small, Go’s run-time uses resizable, bounded stacks To make the stacks small, Go’s run-time uses resizable, bounded stacks. A newly minted goroutine is given a few kilobytes, which is almost always enough. When it isn’t, the run-time grows (and shrinks) the memory for storing the stack automatically, allowing many goroutines to live in a modest amount of memory (runtime 动态调节堆栈内存大小) . If goroutines were just threads, system resources would run out at a much smaller number.
  8. map operations are not atomic
    1. 大多数典型场景无需被多协程安全访问,map 在一些大数据结构或计算同步的一部分,所有 map 加一个 mutex 会降慢大多数程序速度,这个非并发安全 map 设计考虑,也会带来并发安全的问题(需要加锁处理)
    2. Map access is unsafe only when updates are occurring. As long as all goroutines are only reading—looking up elements in the map, including iterating through it using a for rangeloop—and not changing the map by assigning to elements or doing deletions, it is safe for them to access the map concurrently without synchronization.
    3. some implementations of the language contain a special check that automatically reports at run time when a map is modified unsafely by concurrent execution.
  9. accept change ?
    1. the language and libraries are protected by a compatibility promise that prevents changes that break existing programs
    2. A future major release of Go may be incompatible with Go 1, but discussions on that topic have only just begun and one thing is certain: there will be very few such incompatibilities introduced in the process
  10. Go at Google
    1. https://go.dev/talks/2012/splash.article