Golang新人讲义

原版:

[金山文档] Golang讲义 https://kdocs.cn/l/ckLEtJcp4m3B

1.前述
1.1 什么是Golang
来自"官网"的定义: https://golang.google.cn/
Go is an open source programming language that makes it easy to build simple, reliable, and efficient software. 
1.2 谁在用Golang
来自"官方"的数据: https://github.com/golang/go/wiki/GoUsers, 来自"China"部分:
• Baidu
• Alibaba
• Xiaomi
• Tencent
• 163yun - github - Netease Public Cloud
• BaishanCloud
• ByteDance
• Ciprun
• CS2C - github
• deepin - github - a linux distribution aiming to provide an elegant desktop
• EasyAR
• Feiyu
• FunPlus - We Create Leading Innovative and Fun Experiences Worldwide
• FutureBots
• iDCOSCloudBoot
• Inke - the most popular broadcast platform
• Kidswant
• KLOOK
• MegaEase
• Megvii
• Mili
• MobiExchanger - Mobile Internet advertising company
• Momenta
• MZD - github
• OPPO
• Qiniu - github - Qiniu builds and operates one of the largest public cloud services in China, with millions of code written in Go since 2011.
• Rainbond - github - Rainbond is an application centric PaaS
• SenseTime - a global leading A.I. company
• Teambition - github
• TiDB - tweet: Golang in TiDB - github - TiDB is a distributed HTAP database compatible with the MySQL protocol
• Udesk - github
• XiaoChuan
• Xiaoying
• Xunlei
• YeePay
• Yeeuu
• Youmi - a global leading comprehensive mobile internet enterprise
• cshome
• DiDi
• meicai - Catering supply chain service provider
• 360
...
1.3 为啥用Golang
来自"社区"的统计: https://studygolang.com/
• Go编译快
• Go执行快
• Go并发编程方便
• Go有垃圾回收(Garbage Collection, GC)
• Go支持跨平台交叉编译, 一次编写, 到处运行
• Go不用装虚拟机
...
1.4 怎么学Golang
首先: 
选一本入门书, 编写运行"helloworld"!
其次:
• 学习"语言规范"
• 基础语法 
• 面向对象 
• 高级特性
• 学习"标准库"
• 学习"工程管理"
• 学习"内存模型"
• 学习"调度模型"
2.语言规范
2.1 权威指南
•  https://golang.google.cn/ref/spec
2.2 练习范例
• https://gobyexample.com/
2.3 学习"套路"
Golang语言知识点可用下述"套路"串联起来学习! 
• 基础语法
• 字符集
• 词法表: 关键字, 标识符, 字面量, 运算符, 注释符, 分隔符
• 数据表示: 类型, 常量, 变量, 字面量
• 数据计算: 运算符, 表达式, 语句, 函数
• 面向对象
• 高级特性
2.3.1 字符集(Charset)
• 参考: https://golang.google.cn/ref/spec#Characters
• 要点: Golang使用UTF8编码的Unicode字符集. "Source code is Unicode text encoded in UTF-8"
2.3.2 词法表(Lexical)
• 参考: https://golang.google.cn/ref/spec#Lexical_elements
• 要点: Golang的词法元素可以概括成6类, 关键字/标识符/字面量/运算符/定界符!
1) 关键字(Keyword)
• 参考: https://golang.google.cn/ref/spec#Keywords
• 要点: Golang关键字主要分成3大类, 
• 声明定义: package, type, var, const, func, map, chan, struct, interface
• 流程控制: if,else, switch,select,case,default,for,break,continue,fallthrough,goto,return
• 扩展运算符: defer, go, import, range
2) 标识符(Identifier)
• 参考: https://golang.google.cn/ref/spec#Identifiers
• 要点: Golang标识符
• 标识符定义: 由非数字打头的字母,数字,下划线组成. 
• 标识符属性: 作用域与生存期, 见https://golang.google.cn/ref/spec#Declarations_and_scope
• 标识符类别: 从访问控制角度看,
• public(exported) identifier:  大写打头, 包外可见.
• private(unexported) identifier: 小写或下划线打头, 包内可见.
• blank identifier: 下划线, 匿名占位符.
• 预定义标识符: https://golang.google.cn/ref/spec#Predeclared_identifiers
常见的"bool/byte/int/uint/...true/false/iota/nil"是标识符, 不是关键字! 意外不?

3) 字面量(Literal)
• 参考: 
• 布尔字面量: true, false
• 整数字面量: https://golang.google.cn/ref/spec#Integer_literals
• 浮数字面量: https://golang.google.cn/ref/spec#Floating-point_literals
• 复数字面量: https://golang.google.cn/ref/spec#Imaginary_literals
• 字符字面量: https://golang.google.cn/ref/spec#Rune_literals
• 字串字面量: https://golang.google.cn/ref/spec#String_literals
• 复合字面量: https://golang.google.cn/ref/spec#Composite_literals
• 函数字面量: https://golang.google.cn/ref/spec#Function_literals
• 要点: 
字面量是直接写在源码里面的"数据表示", 例如: 123, "abc", []string{...}
常量或变量需要定义某个"标识符", 是间接写在源码里面的"数据表示"! 

4) 运算符(Operator)
• 参考: https://golang.google.cn/ref/spec#Operators
• 要点: Golang运算符
• 运算符属性: 优先级与结合性, 
• 运算符类别:
• 算术运算符: +,-,*,/,%,++,--
• 比较运算符: ==, !=, >, <, >=, <=
• 逻辑运算符: &&, ||, !
• 地址运算符: &(取地址), *(解地址)
• 管道运算符: <-
• 成员运算符: .
• 类型转换符: .(T)
• 其他...

5) 注释符(Comment)
• 参考: https://golang.google.cn/ref/spec#Comments
• 要点: Golang注释有2种,
• 单行注释: //
• 多行注释 : /*...*/
一般地, godoc使用"离声明(前)最近"的注释做为"文档"!

6) 分隔符(Delimiter)
• 参考: https://golang.google.cn/ref/spec#Semicolons
• 要点: Golang分隔符包括空白( 	vf

...等)与分号(;).
一般地, 编译器都能"智能"地在行末插入分号(;),  如果无法确定语句(Statement)能不能换行? 请回头细读"参考"的详细规则!

2.3.3 数据表示(Data Representation)

1) 类型(Types)
• 参考: https://golang.google.cn/ref/spec#Types
• 要点:
• 类型分类

一种好的"类型分类"可以帮助更好地掌握Golang!

• 标(量)值类型(scalar-value-types), 0值非nil
• 布尔类: bool
• 整数类: int/int8/int16/int32/int64, uint/uint8/uint16/uint32/uint64, uintptr
• 浮数类: float32/float64
• 复数类: complex64/complex128
• 字符类: byte/rune/string

其中, byte是uint8的类型别名, rune是int32类型别名.

• 聚(合)值类型(aggregate-value-types), 0值非nil
• 数组: array
• 结构: struct

• 引用类型(reference-types), 0值为nil
• 分片: slice
• 映射: map
• 管道: chan

• 函数类型(function-types), 0值是nil
• 指针类型(pointer-types), 0值是nil
• 接口类型(interface-types), 0值是nil

为什么这样分类?
       1. 标(量)值类型才能定义常量!
const a int = 1 // 正确
const b []int = ... // 错误
2. 值类型(标量值类型/聚合值类型)的0值非nil, 无法与nil比较. 例如: 
var a int
if a==nil { // 错误
...
}
3. 引用类型要么用"字面量"初始化, 要么用make()内置函数初始化!
var a []int = []int{1,2,3} // 字面量初始化
var b []int = make([]int,0,3) // make()初始化
4.   函数类型才能被执行
var f func()
f() // 正确
var b string
b() // 错误
5.  接口类型才能reflection, type-assertion, type-switch
var a string
if v, ok := a.(string); ok { // 错误, a不是接口类型
...
}
var b interface{} = a
if v, ok := b.(string); ok { // 正确, b是接口类型
...
} 
6. 接收者类型不能是pointer-types, interface-types.
type PString *string
func (ps PString) Info(){ // 错误, Invalid receiver type 'PString' ('PString' is a pointer type)
...
}
7. 函数形参要用T, 还是*T?
func Test(a string, b []byte, c *[2]byte){
...
}
函数定义, 如果形参不作为"左值", 一般地:
- 标(量)值类型使用T
- 聚(合)值类型使用*T, 避免内存复制
- 其他类型使用T, 0值为nil
8. 指针类型才能与unsafe.Pointer转换
var buf []byte
var str string = *(*string)(unsafe.Pointer(&buf))
var nbuf = *(*[]byte)(unsafe.Pointer(&str))
9. 接口类型具有二元组(T,V)特性, 每个接口变量记录被赋值目标的类型(Type)与值(Value). 接口变量相等(==)当且仅当类型(Type)与值(Value)都相等.
    var sp *string          // sp is nil
    var iv interface{} = sp // iv is not nil(T is *string, V is nil)
    var iv2 interface{}     // iv2 is nil(T is nil, V is nil)
    fmt.Println(iv == iv2)  // false

• 类型转换Type-Conversions, 见https://golang.google.cn/ref/spec#Conversions
类型转换只能在"兼容"类型间进行!  例如: int --> int32

• 类型断言Type-Assertions, 见https://golang.google.cn/ref/spec#Type_assertions
类型断言的参数为nil会panic !

• 类型开关Type-Switchs, 见https://golang.google.cn/ref/spec#Switch_statements
类型开关的参数为nil会匹配"case nil" !

2) 字面量(Literal)
• 布尔: true, false
• 整数: 2进制(0b/0B打头), 8进制(0打头), 10进制, 16进制(0x/0X打头)
• 浮数: 小数, 指数
• 复数: r+mi
• 字符: 'x', 单引括住
• 字串: "....", `....`, 双引或反引括住
• 数组: [n]T{....}
• 分片: []T{...}
• 映射: map[K]V{....}
• 函数: func(...){....}
• 其它见"词法表-字面量"介绍, 此处不再赘述!

3) 常量(Constant)
• 参考: https://golang.google.cn/ref/spec#Constants
• 要点: 
• 常量类型必须是"标(量)值类型". 见"类型"一节的分类描述!
There are boolean constants, rune constants, integer constants, floating-point constants, complex constants, and string constants. 
• iota实质是"下标". 见https://golang.google.cn/ref/spec#Iota
Its value is the index of the respective ConstSpec in that constant declaration, starting at zero.

const(
  e1 = iota // e1=0, 语句下标是0
  e2 = 123 // e2 = 123
  e3 = iota // e3 = 2, 语句下标是2
)
• 常量声明向前看. (与后面"变量声明向后看"对应)
   const (
        a int32 = iota
        b
        c float32 = 2 * iota
        d
        e int64 = 1
        f
        g
    )
    fmt.Println("a:", a) // a: 0
    fmt.Println("b:", b) // b: 1
    fmt.Println("c:", c) // c: 4
    fmt.Println("d:", d) // d: 6
    fmt.Println("e:", e) // e: 1
    fmt.Println("f:", f) // f: 1
    fmt.Println("g:", g) // g: 1
4) 变量(Variables)
• 参考: https://golang.google.cn/ref/spec#Variables
• 要点:
• 变量声明向后看!
var a, b, c, d, e, f string = "a"
// a, b, c, d, e, f都是string, 值为a
• 变量短声明.  见https://golang.google.cn/ref/spec#Short_variable_declarations
• 条件: 声明左侧标识符至少一个在块作用域尚未定义!
• 结果: 声明左侧标识符全部都会在块作用域重新定义! 很容易屏敝外部同名变量. 很"坑"!
var locale string = "en-US"
if locale, ok := "zh-CN", true; ok {
   fmt.Println("inner locale is:", locale) // inner locale is: zh-CN
}
fmt.Println("outer locale is:", locale) // outer locale is: en-US

2.3.4 数据计算(Data Computation)

1) 运算符(Operator)
• 见"词法表-运算符"介绍, 此处不再赘述!
2) 表达式(Expression)
• 参考: https://golang.google.cn/ref/spec#Expressions
3) 语句(Statement)
• 参考: https://golang.google.cn/ref/spec#Statements
• 要点: 
• Empty statements
• Label statements
• Expression statements
• Send statements
• IncDec statements
• Assignment statements
• If statements(2种形式)
• If-Condition
if x==3 {...}
• If-InitStmt-Condition
if x:=2*i; x==3 {...}
• Switch statements(2种形式)
• Expression-Switchs

switch x {  // Switch-Condition
case 1, 2:...
case 3: ...
case 4: ...
default: ...
}
或 
switch x:= 2*i; x < 100 { // Switch-InitStmt-Condition
...
}

switch { // Switch-Matching, 叠加if-else
case x==1 || x==2:...
case x==3: ...
case x==4: ...
default: ...
}
• Type-Switchs
switch x.(type) {
case nil: ...
case int: ...
case string: ...
default: ...
}
• For statements(4种形式)
• For-Loop
for {....} // 无条件循环
• For-Condition
for x < 100 { // while-do
    ...
    x++
}
• For-InitStmt-Condition-PostStmt
for i:=0;i<100;i++ {
...
}
• For-Range
var a []int = ...
for i, v := range a { // 遍历
...
}
• Go statement
• Select statement
• Return statement
• Break statement
• Continue statement
• Goto statement
• Fallthrought statement
• Defer statement
4) 函数(Function)
• 参考: https://golang.google.cn/ref/spec#Function_declarations
• 要点: Golang提供了强大的"函数"机制! 
• 函数声明: 函数声明用于定义函数常量, 必须位于顶层! 函数接收者是Golang特有
见https://golang.google.cn/ref/spec#Function_declarations

• 函数类型: 函数类型用于修饰函数变量. 
见https://golang.google.cn/ref/spec#Function_types

• 函数字面量: 函数字面量就是匿名函数, 结合闭包使用超级灵活. 
见https://golang.google.cn/ref/spec#Function_literals

• 内置函数: 内置函数可以看作"运算符扩展".
见https://golang.google.cn/ref/spec#Built-in_functions

• 函数原型的形参类型是用T, 还是*T?
如果你在定义函数时纠结形参类型, 是用原生类型(T), 还是指针类型(*T)? 下面是几条有用的建议(类型分类见上):
i.若形参要作为左值必须传递指针类型(*T), 否则见下.
ii.标(量)值类型(Scalar Type)使用原生类型(T), 例如: int, float64, string...
iii.复(合)值类型(Aggregate Type)使用指针类型(*T), 例如: array, struct
iv.其他类型使用原生类型(T), 例如: slice, map, chan....

• Golang(1.x)没有函数模板, 没有函数重载! 单一函数可能针对不同类型衍生多个版本! 处理技巧就是: 该复制就复制, 别钻牛角尖... 例如:
func GetString(v interface{}) string...
func GetInt(v interface{}) int...
...

2.3.5 面向对象(OOP)
OOP四大特征: 抽象, 封装, 继承, 多态!
Golang通过扩展Struct, Function与Interface三个原语实现对OOP的支持!
• struct/interface支持"embedded field"语法实现组合继承.
见https://golang.google.cn/ref/spec#Struct_types

• function扩展"Receiver"语法实现对象方法
见https://golang.google.cn/ref/spec#Method_declarations

• interface的二元组(T,V)特性及"duck-typing"机制实现调用多态

1) 如何定义类(class)与方法(method)
• 通过type定义class类, 可以是int, string, struct...等具体类型, 但不能是接口类型.
• 通过带Receiver的function定义method方法.
type Class struct{
  field string
  ...
}
func (c *Class)GetField()string{
   return c.Field1
}
2) 如何创建对象(object)
• 通过var声明或new()创建对象
var c1 Class
c2 := new(Calss)
3) 如何实现抽象(abstract)
• 分析处理逻辑,分成"不变"与"变化", 各自定义成独立的方法. 
4) 如何实现封装(encapsulation)
• 通过Field或Method标识符实现数据封装. Public Identifier包外可见, Private Identifier包内可见! 
5) 如何实现继承(inheritance)与改写(override)
• Struct与Interface都支持Embedded Field语法, 通过"组合"的方式实现继承!
type Derive struct{
   Class // 组合
   info string
}
func (d *Derive) GetField() string{
    return d.info
}

6) 如何实现多态(polymorphism)
• 通过"interface + duck-typing"的模式实现多态
type Fielder interface{
    GetField() string
}

func PrintField(f Fielder) {
   fmt.Println(f.GetField())
}

func main(){
   c := new(Class)
   PrintField(c) // 打印Class.field值
   d := new(Derive)
   PrintField(d) // 打印Derive.info的值
}

附述一: Function Receiver语法

function receiver语法详解见https://golang.google.cn/ref/spec#Method_declarations

• T必须是定义当前包(package)里的原生类型(raw type)! 2个必要条件:
• 当前包(package)
• 原生类型(raw type)
type T *string

func (t *T)Test()  {
    // Invalid receiver type 'T' ('T' is a pointer type)
} 
• T的Method也是*T的Method, 反之不成立! 见https://golang.google.cn/ref/spec#Method_sets

• T与*T的选择考虑:
R(function receiver)是用T, 还是用*T, 下面是一些建议:
• R要作为左值必须是用*T.  
• 其他场景取决设计初衷, 用*T强制调用调用对象必须是pointer type, 用T则raw type与pointer type都可以. 原因见上.

附述二: interface二元组(T,V)特性
• interface二元组(T,V): 每个interface type包含二个元素(type, value), 判断interface variables是否相同要求type与value都相同!
• interface赋值规则: 
• 若右值是interface type, 则将右值的(type, value)赋给左值.
• 若右值非interface type, 则将右值的具体类型赋给左值的type, 右值自己赋给左值的value. 
所以, 当用非interface type给interface赋值时, 无论右值是否为nil, 左值interface都不也再是nil. 见https://golang.google.cn/doc/faq#nil_error 

附述三: interface duck-typing实现机制

鸭子类型: 类型只要实现了接口的所有方法, 就称类型实现了接口. 
• 万能接口: 所有类型都实现了空接口"interface{}".
var v interface{}
v = 1
v = "a"
v = 1.234
• 断言习惯: 由于"接口duck-typing实现机制"过于灵活, 习惯在实现类型定义处加上"断言", 在接口变化时触发编译错误!
type Class struct{
  field string
  ...
}
var _ Fielder = (*Class)(nil) // 断言类型Class是接口Fielder的实现者.

2.3.6 高级特性
1) 自动垃圾回收
golang的垃圾回收(GC)封装成runtime模块, 并且随着golang版本不断升级与优化. 有兴趣的同学可以阅读下述文章了解部分细节: 
• GO GC 垃圾回收机制: https://segmentfault.com/a/1190000018161588
• Eliminate STW stack re-scanning: https://github.com/golang/proposal/blob/master/design/17503-eliminate-rescan.md

2) 更丰富的内置类型
slice
map
chan
error
interface{}
参考
built-in functions: https://golang.google.cn/ref/spec#Types

3) 函数与闭包
    golang提供了更多的函数特性:
• 函数类型(function type):  https://golang.google.cn/ref/spec#Function_types
• 函数字面量(function literal): https://golang.google.cn/ref/spec#Function_literals
• 命名/多个返回值(named/multiple return values): 
• 延迟(defer): https://golang.google.cn/ref/spec#Defer_statements
• 闭包(closures)

4) 异常处理
• defer
• panic
• recover

5) 类型与接口
golang提供2种灵活的"type"定义方式, 以及"duck-typing"的接口实现机制.
• 类型定义(type declaration)
• 类型别名(type aliases)
• 鸭子类型(duck typing)接口实现
• 万能空接口(interface{}): https://golang.google.cn/ref/spec#Interface_types
• 接口二元组(T,V)特性

6) 支持反射
golang提供reflect支持接口类型的运行时类型反射
• RTTI: runtime type information, 运行时类型信息
• reflect package: https://golang.google.cn/pkg/reflect/

7) 并发与协程
Don't communicate by sharing memory; share memory by communicating. (R. Pike)
golang提供"语言级的协程原语"与丰富的同步库, 能够"非常好"地支持CSP(Communicating Sequential Process)与Actor并发编程模型.
• go
• chan
• sync package: https://golang.google.cn/pkg/sync/

8) 调用C代码
golang提供cgo支持在"Go"直接调用"C"代码
• 入门范例 https://blog.golang.org/cgo
• 详细指南 https://pkg.go.dev/cmd/cgo

3.标准库
权威指南: https://golang.google.cn/pkg/
学习范例: 
• golang常用标准库: https://www.jianshu.com/p/33fc2a3bed9a
• golang标准库分析: https://www.widuu.com/tag/GO%E5%9F%BA%E7%A1%80.html
4.工程管理
4.1 go工程结构
4.1.1 基于GOPATH的工程结构
$GOPATH
 |__<workspace...>
    |__bin/
    |__pkg/
    |__src/
       |__<package...>
          |__<file...>
          |__...
1.workspace依赖通过$GOPATH添加
2.workspace要求包含src/pkg/bin, 其中src是必需的.
3.src包含多个package
4.package包含多个file

4.1.2 基于GOMOD的工程结构
<module>
|__go.mod
|__go.sum
|__<package...>
   |__<file...>
1.module依赖通过go.mod添加
2.module直接包含package, 虽不再要求src/pkg/bin.
3.package包含多个file

可见gomod大大简化了golang的工程结构!

4.1.3 相关概念梳理
• program: 名字为main的package, 每个project只会有一个program!
• package: 包含go源文件的目录
• package-path: 
• GOPATH工程结构中表示到src的相对路径
• GOMOD工程结构中表示前缀为"module-path"的相对路径
• package-name:
在file中package语句定义的值, 相同package-path下面的package-name必须相同. 例如: ossi
package ossi

import (
    "ksogitlab.wps.kingsoft.net/hezhaowu1/ossi/kits"
)
• module-path:
在go.mod中module指令定义的值, moudle里面的package-path必须包含module-path前缀(见上).  例如: ksogitlab.wps.kingsoft.net/hezhaowu1/ossi
# go.mod
module ksogitlab.wps.kingsoft.net/hezhaowu1/ossi

go 1.13

4.2 go依赖管理

go发行历史先后推出过3种"依赖管理"相关的工具: internal, vendor, gomod... 

4.2.1 internal(GO1.4)
• 参考: https://golang.google.cn/doc/go1.4#internalpackages
• 要点: 内部包只能被相同前缀的其他包引用. 例如: 内部包“.../a/b/c/internal/d/e/f” 只能被package-path前缀为".../a/b/c"的其他包调用.

4.2.2 vendor(GO1.5)
• 参考: 
• https://golang.google.cn/cmd/go/#hdr-Vendor_Directories
• https://golang.org/s/go15vendor
• 要点:  
• go优先从最近的vendor查找依赖包.
• 不同vendor的相同package会被认为不同. 巨坑无比!
workspace
|_src
  |__pkg1
  |   |__vendor
  |      |__a/b/c
  |__pkg2
     |__vendor
        |__a/b/c

# 编译器会认为二个vendor下面"a/b/c"是完全不同的包!

4.2.3 gomod(GO1.11)
• 参考: https://golang.google.cn/ref/mod
• 要点: 
• gomod是GO官方推出的管理依赖的协议与工具集, 它支持版本,缓存,校验...等功能.
• kgoproxy(https://kgoproxy.kingsoft.net)是公司内部的gomod代理服务, 下载速度快, 支持发布私模块与第三方定制包, 并且集成了安全平台流程规范. 配置方式:
"GOPROXY=https://kgoproxy.kingsoft.net;GOSUMDB=off;GOPRIVATE=ksogit.kingsoft.net"

4.3 go单元测试与基准测试
• 参考: https://golang.google.cn/doc/code#Testing
• 要点: go自带go test命令,自动执行单元测试与基准测试
• 测试文件后缀必须"xxx_test.go", 其中xxx表示被测文件名称
• 单元测试原型必须"func TestXXX(t *testing.T)", 其中XXX表示被测函数名称
• 基准测试原型必须"func BenchmarkXXX(b *testing.B)", 其中XXX表示被测函数名称.
func TestTest(t *testing.T) {
    ...
}

func BenchmarkTest(b *testing.B) {
    ...
}

4.4 go工具命令
# windows
> go help
Go is a tool for managing Go source code.

Usage:

        go <command> [arguments]

The commands are:

        bug         start a bug report
        build       compile packages and dependencies
        clean       remove object files and cached files
        doc         show documentation for package or symbol
        env         print Go environment information
        fix         update packages to use new APIs
        fmt         gofmt (reformat) package sources
        generate    generate Go files by processing source
        get         download and install packages and dependencies
        install     compile and install packages and dependencies
        list        list packages or modules
        mod         module maintenance
        run         compile and run Go program
        test        test packages
        tool        run specified go tool
        version     print Go version
        vet         report likely mistakes in packages

Use "go help <command>" for more information about a command.

Additional help topics:

        buildconstraint build constraints
        buildmode       build modes
        c               calling between Go and C
        cache           build and test caching
        environment     environment variables
        filetype        file types
        go.mod          the go.mod file
        gopath          GOPATH environment variable
        gopath-get      legacy GOPATH go get
        goproxy         module proxy protocol
        importpath      import path syntax
        modules         modules, module versions, and more
        module-get      module-aware go get
        module-auth     module authentication using go.sum
        packages        package lists and patterns
        private         configuration for downloading non-public code
        testflag        testing flags
        testfunc        testing functions
        vcs             controlling version control with GOVCS

Use "go help <topic>" for more information about that topic.
4.5 go环境变量
# windows
>go env
set GO111MODULE=off
set GOARCH=amd64
set GOBIN=
set GOCACHE=D:golang-repositoryGOCACHE
set GOENV=C:UsersJasonAppDataRoaminggoenv
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=D:golang-repositoryGOPATHpkgmod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=D:golang-repositoryGOPATH
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=c:go
set GOSUMDB=off
set GOTMPDIR=
set GOTOOLDIR=c:gopkg	oolwindows_amd64
set GOVCS=
set GOVERSION=go1.16.5
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=C:WINDOWSTEMPgo-build2970469303=/tmp/go-build -gno-record-gcc-switches
go开发IDE
• 参考: https://www.jetbrains.com/go/
5.内存模型
• 参考: https://golang.google.cn/ref/mem
中译版<Go的内存模型>https://studygolang.com/articles/1597

6.调度模型
• 参考: 推荐干货
• <深度解密Go语言之 scheduler>https://www.cnblogs.com/qcrao-2018/p/11442998.html
• <Golang调度器GMP原理与调度全分析>https://studygolang.com/articles/27069?fr=sidebar
• <Part I - OS Scheduler>https://www.jianshu.com/p/c38a22d8f913
• <Part II - Go Scheduler>https://www.jianshu.com/p/0ab4d1b1db45
• <Part III - Concurrency>https://www.jianshu.com/p/44be951fc19f

原文地址:https://www.cnblogs.com/zolo/p/15093366.html