diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 188e9ff..0000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.md linguist-language=Go \ No newline at end of file diff --git a/.gitignore b/.gitignore index 610b714..5c77697 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,7 @@ trunk/.idea/ */.DS_Store # production file -dist/ \ No newline at end of file +dist/ + +# go practice file +*.go \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b906d4f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.formatOnType": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true /*自动格式化js*/, + "source.fixAll.markdownlint": true /*自动格式化markdown*/ + } +} diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/01-Go\347\256\200\344\273\213.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/01-Go\347\256\200\344\273\213.md" index 9ec3b49..68f7e9c 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/01-Go\347\256\200\344\273\213.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/01-Go\347\256\200\344\273\213.md" @@ -53,7 +53,7 @@ export GOPATH=~/go # golang包的本地安装位置 export GOPROXY=https://goproxy.io,direct # golang包的下载代理,回源地址获取 export GO111MODULE=on # 开启go mod模式 export PATH=$PATH:$GOROOT/bin # go本身二进制文件的环境变量 -export PATH=$PATH:$GOPATH/bin # go第三方二进制文件的环境便令 +export PATH=$PATH:$GOPATH/bin # go第三方二进制文件的环境变量 # 重启环境 source /etc/profile diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-2-\345\255\227\347\254\246\344\270\262.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-2-\345\255\227\347\254\246\344\270\262.md" index 13db627..4afd7da 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-2-\345\255\227\347\254\246\344\270\262.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-2-\345\255\227\347\254\246\344\270\262.md" @@ -124,7 +124,7 @@ fmt.Printf("%T \n", string(num)) // string package main import ( - "bytes" + "strings" "fmt" ) @@ -134,7 +134,7 @@ func main() { str2 := " world" //创建字节缓冲 - var stringBuilder bytes.Buffer + var stringBuilder strings.Builder //把字符串写入缓冲 stringBuilder.WriteString(str1) @@ -170,7 +170,7 @@ Join(s []string, str string) string Replace(str,old,new string,n int) string //字符串str按照s分割,返回切片 -Splite(str,s string)[]string +Split(str,s string)[]string // 去除头部、尾部指定的字符串 Trim(s string, cutset string) string @@ -215,6 +215,6 @@ func main() { h, _ := strconv.ParseInt("1234", 10, 64) i, _ := strconv.ParseUint("12345", 10, 64) j, _ := strconv.Atoi("1023") - fmt.Println(f, g, h, j, i, j) // false 123.23 1234 1023 12345 1023 + fmt.Println(f, g, h, i, j) // false 123.23 1234 12345 1023 } -``` \ No newline at end of file +``` diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-4-\347\273\223\346\236\204\344\275\223.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-4-\347\273\223\346\236\204\344\275\223.md" index f2a02ef..a57bc74 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-4-\347\273\223\346\236\204\344\275\223.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/06-\345\200\274\347\261\273\345\236\213-4-\347\273\223\346\236\204\344\275\223.md" @@ -19,7 +19,7 @@ p3.name = "zs" //这里的.语法只是语法糖,将p3.name转换成 p3.age = 27 //直接声明 -var s4 Person +var p4 Person p4.name = "ww" p4.age = 30 ``` @@ -100,7 +100,7 @@ type Person struct { } type Student struct { - Person // 匿名字段,那么默认Student就包含了Human的所有字段 + Person // 匿名字段,那么默认Student就包含了Person的所有字段 classroom string } ``` @@ -138,4 +138,4 @@ func main() { } ``` -贴士:如果Person和Student中都有同一个字段,那么Go会优先访问当前层。例如二者都有`tel`字段,那么`s.tel`将会访问的是Student中的数据。 \ No newline at end of file +贴士:如果Person和Student中都有同一个字段,那么Go会优先访问当前层。例如二者都有`tel`字段,那么`s.tel`将会访问的是Student中的数据。 diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-1-\345\210\207\347\211\207.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-1-\345\210\207\347\211\207.md" index fa1df87..80a2d2e 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-1-\345\210\207\347\211\207.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-1-\345\210\207\347\211\207.md" @@ -23,7 +23,7 @@ slice3 := []int{1,2,3,4,5} // 创建长度为5,容量为5,并已经初始化 var arr = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'} // 声明两个含有byte的slice -ar a, b []byte +var a, b []byte // a指向数组的第3个元素开始,并到第五个元素结束,现在a含有的元素: ar[2]、ar[3]和ar[4] a = arr[2:5] @@ -170,4 +170,4 @@ func main() { fmt.Printf("main---%p\n", s1) // 不会因为test函数内的append而改变 fmt.Println("main---", s1) // [ 0 0 0] } -``` \ No newline at end of file +``` diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-2-\351\233\206\345\220\210.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-2-\351\233\206\345\220\210.md" index 4b099a4..8b1b564 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-2-\351\233\206\345\220\210.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/09-\345\274\225\347\224\250\347\261\273\345\236\213-2-\351\233\206\345\220\210.md" @@ -53,7 +53,7 @@ map的遍历:同数组一样,使用for-range 的结构遍历 - map的长度是不固定的,也就是和slice一样,也是一种引用类型 - 内置的len函数同样适用于map,返回map拥有的key的数量 - go没有提供清空元素的方法,可以重新make一个新的map,不用担心垃圾回收的效率,因为go中并行垃圾回收效率比写一个清空函数高效很多 -- map和其他基本型别不同,它不是thread-safe,在多个go-routine存取时,必须使用mutex lock机制 +- map和其他基本类型不同,它不是thread-safe,在多个go-routine存取时,必须使用mutex lock机制 #### 1.3 并发安全的map @@ -120,4 +120,4 @@ func main() { } ``` -注意:map没有提供获取map数量的方法,可以在遍历时手动计算。sync.Map为了并发安全。损失了一定的性能。 \ No newline at end of file +注意:map没有提供获取map数量的方法,可以在遍历时手动计算。sync.Map为了并发安全。损失了一定的性能。 diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/10-\345\207\275\346\225\260-1-\345\207\275\346\225\260\347\256\200\344\273\213.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/10-\345\207\275\346\225\260-1-\345\207\275\346\225\260\347\256\200\344\273\213.md" index 94548c3..df4ca21 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/10-\345\207\275\346\225\260-1-\345\207\275\346\225\260\347\256\200\344\273\213.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/10-\345\207\275\346\225\260-1-\345\207\275\346\225\260\347\256\200\344\273\213.md" @@ -163,7 +163,7 @@ func Test(f MyMath, a , b int) int{ #### 3.1 init函数 -Go语言中,除了可以在全局声明中初始化实体,也可以在init函数中初始化。init函数是一个特殊的函数,它会在包完成初始化后自动执行,执行优先级高于main函数,并且不能手动调用init函数,每一个文件有且仅有一个init函数,初始化过程会根据包的以来关系顺序单线程执行。 +Go语言中,除了可以在全局声明中初始化实体,也可以在init函数中初始化。init函数是一个特殊的函数,它会在包完成初始化后自动执行,执行优先级高于main函数,并且不能手动调用init函数,每一个文件可以有多个init函数,初始化过程会根据包的依赖关系顺序单线程执行。 ```go package main import ( diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/11-\351\235\242\345\220\221\345\257\271\350\261\241-1-\346\236\204\351\200\240\345\207\275\346\225\260\344\270\216\346\226\271\346\263\225.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/11-\351\235\242\345\220\221\345\257\271\350\261\241-1-\346\236\204\351\200\240\345\207\275\346\225\260\344\270\216\346\226\271\346\263\225.md" index b66a7b4..edb8350 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/11-\351\235\242\345\220\221\345\257\271\350\261\241-1-\346\236\204\351\200\240\345\207\275\346\225\260\344\270\216\346\226\271\346\263\225.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/11-\351\235\242\345\220\221\345\257\271\350\261\241-1-\346\236\204\351\200\240\345\207\275\346\225\260\344\270\216\346\226\271\346\263\225.md" @@ -160,39 +160,43 @@ Go的方法是一种作用于特定类型变量的函数,这种特定类型的 方法与函数的区别就是:函数没有作用对象。 -上述Person案例中,接收器类型是`*Person`,属于指针类型,非常接近Java中的`this`,由于指针的特性,调用方法时,修改接收器指针的任意长远变量,在方法结束后,修改都是有效的。 +指针接收器传入的是 struct 本身,指针接收器可以读写 struct 中的内容,在方法结束后,修改都是有效的。 + +非指针接收器传入的是 struct 的 copy 副本,非指针接收器只能读取 struct 中的数据但是不能写入,如果写入的话也只是写入到 struct 的备份中而已。 + +示例如下: -当方法作用于非指针接收器时,Go语言会在代码运行时将接收器的值复制一份,在非指针接收器的方法中可以获取接收器的成员值,但修改后无效,如下所示: ```go package main import "fmt" -//定义一个表示点的结构体 -type Point struct { - X int - Y int +type student struct { + age int8 +} + +//指针接收器 +func(s *student) ageAdd1() { + s.age += 1 } //非指针接收器 -func (p Point) Add(otherP Point) Point { - return Point{ - p.X + otherP.X, - p.Y + otherP.Y, - } +func(s student) ageAdd2() { + s.age += 1 } func main() { + student := new(student) - p1 := Point{1, 1} - p2 := Point{2, 2} - - result := p1.Add(p2) + student.ageAdd1() + fmt.Println(student.age) // 1 传入指针,原值 + 1,为 1 - fmt.Println(result) // {3 3} + student.ageAdd1() + fmt.Println(student.age) // 2 传入指针,原值 + 1,为 2 + student.ageAdd2() + fmt.Println(student.age) // 2 传入复制体,复制体 + 1,所以原值还是 2 } - ``` 一般情况下,小对象由于复制时速度较快,适合使用非指针接收器,大对象因为复制性能较低,适合使用指针接收器,此时再接收器和参数之间传递时不进行复制,只传递指针。 \ No newline at end of file diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-1-\346\216\245\345\217\243\347\232\204\344\275\277\347\224\250.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-1-\346\216\245\345\217\243\347\232\204\344\275\277\347\224\250.md" index 56c444e..088c131 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-1-\346\216\245\345\217\243\347\232\204\344\275\277\347\224\250.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-1-\346\216\245\345\217\243\347\232\204\344\275\277\347\224\250.md" @@ -193,5 +193,5 @@ func main() { | 切片 | 不可比较,会发生宕机错误 | | 通道 | 可比较,必须由同一个make生成,即同一个通道才是true | | 数组 | 可比较,编译期即可知道是否一致 | -| 结构体 | 可比较,可诸葛比较结构体的值 | +| 结构体 | 可比较,可逐个比较结构体的值 | | 函数 | 可比较 | \ No newline at end of file diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-2-\346\226\255\350\250\200\344\270\216\345\244\232\346\200\201.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-2-\346\226\255\350\250\200\344\270\216\345\244\232\346\200\201.md" index 52da2c6..6550b14 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-2-\346\226\255\350\250\200\344\270\216\345\244\232\346\200\201.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/12-\346\216\245\345\217\243\347\261\273\345\236\213-2-\346\226\255\350\250\200\344\270\216\345\244\232\346\200\201.md" @@ -34,7 +34,7 @@ func (b *Bird) Fly() { fmt.Printf("%s 在 飞\n", b.Name) } -// 一定一个鱼类:其呼吸方式是在水下 +// 定义一个鱼类:其呼吸方式是在水下 type Fish struct { Name string Kind string @@ -92,7 +92,7 @@ func Display(a Animal) { ## 二 接口类型转换 -在接口定义时,其类型已经确定,因为接口的本质是方法签名的集合,如果两个接口的方法签名结合相同(顺序可以不同),则这2个接口之间不需要强制类型转换就可以相互赋值,因为go编译器在校验接口是否能赋值时,比较的是二者的方法集。 +在接口定义时,其类型已经确定,因为接口的本质是方法签名的集合,如果两个接口的方法签名集合相同(顺序可以不同),则这2个接口之间不需要强制类型转换就可以相互赋值,因为go编译器在校验接口是否能赋值时,比较的是二者的方法集。 在上一节中,函数Display接收的是Animal接口类型,在断言后转换为了别的类型:*Bird(实现类指针类型): ```go diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/14-\346\227\266\351\227\264\346\223\215\344\275\234.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/14-\346\227\266\351\227\264\346\223\215\344\275\234.md" index 0b1a2df..99b91cc 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/14-\346\227\266\351\227\264\346\223\215\344\275\234.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/14-\346\227\266\351\227\264\346\223\215\344\275\234.md" @@ -20,7 +20,7 @@ Go的时间格式化必须传入Go的生日:`Mon Jan 2 15:04:05 -0700 MST 2006 ```go nowTime := time.Now() stringTime := nowTime.Format("2006年1月2日 15:04:05") - fmt.Println(stringTime) // 2019年01月01日 13:55:30 + fmt.Println(stringTime) // 2019年1月1日 13:55:30 ``` Go的时间解析: @@ -78,7 +78,7 @@ Go的时间解析: ## 二 时间中的通道操作(定时器) -标准库中的Timer可以让用户自定义一个定时器,在用对select处理多个channel的超时、单channel读写的超时等情形时很方便: +标准库中的Timer可以让用户自定义一个定时器,在对用select处理多个channel的超时、单channel读写的超时等情形时很方便: ```go timer := time.NewTimer(time.Second * 3) // 类型为 *time.Timer ch := timer.C // timer内部包含一个通道 @@ -104,4 +104,4 @@ time.After函数的使用: ch := time.After(time.Second * 3) // 底层其实是 new Timer(d).C newTime := <-ch // 阻塞3秒 fmt.Println(newTime) -``` \ No newline at end of file +``` diff --git "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/15-\345\217\215\345\260\204-1-\346\246\202\350\277\260.md" "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/15-\345\217\215\345\260\204-1-\346\246\202\350\277\260.md" index 28f88b8..be704d0 100644 --- "a/01-\345\237\272\347\241\200\350\257\255\346\263\225/15-\345\217\215\345\260\204-1-\346\246\202\350\277\260.md" +++ "b/01-\345\237\272\347\241\200\350\257\255\346\263\225/15-\345\217\215\345\260\204-1-\346\246\202\350\277\260.md" @@ -2,7 +2,7 @@ 反射是指在程序运行期对程序本身进行访问和修改的能力,即可以在运行时动态获取变量的各种信息,比如变量的类型(type),类别(kind),如果是结构体变量,还可以获取到结构体本身的信息(字段与方法),通过反射,还可以修改变量的值,可以调用关联的方法。 -反射常用在框架的开发上,一些常见的案例,如JSON序列化时候tag标签的产生,适配器函数的制作等,都需要用到反射。反射的两个使用常见使用场景: +反射常用在框架的开发上,一些常见的案例,如JSON序列化时候tag标签的产生,适配器函数的制作等,都需要用到反射。反射的两个常见使用场景: - 不知道函数的参数类型:没有约定好参数、传入类型很多,此时类型不能统一表示,需要反射 - 不知道调用哪个函数:比如根据用户的输入来决定调用特定函数,此时需要依据函数、函数参数进行反射,在运行期间动态执行函数 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-1-\345\271\266\345\217\221\347\256\200\347\225\245-\346\246\202\350\277\260.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-1-\345\271\266\345\217\221\347\256\200\347\225\245-\346\246\202\350\277\260.md" index 1a537c6..f261d7c 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-1-\345\271\266\345\217\221\347\256\200\347\225\245-\346\246\202\350\277\260.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-1-\345\271\266\345\217\221\347\256\200\347\225\245-\346\246\202\350\277\260.md" @@ -92,7 +92,7 @@ 除了使用同步方式来实现并发程序数据的交互之外,还可以使用数据传递方式(也称为通信)。 -该方式可以使数据不加延迟的发送给数据接收方。即使数据接收方还没有为接收数据做好准备,也不会造成数据发送方的等待。数据会被临时存储在一个称谓通信缓存的数据结构中。通信缓存是一种特殊的数据结构,可以同时被多个程序使用,数据接收方可以在准备就绪之后按照数据存入通信缓存的顺序接收它们。 +该方式可以使数据不加延迟的发送给数据接收方。即使数据接收方还没有为接收数据做好准备,也不会造成数据发送方的等待。数据会被临时存储在一个称为通信缓存的数据结构中。通信缓存是一种特殊的数据结构,可以同时被多个程序使用,数据接收方可以在准备就绪之后按照数据存入通信缓存的顺序接收它们。 ## 四 各个语言的并发理念 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-2-\345\271\266\345\217\221\347\256\200\347\225\245-\345\244\232\350\277\233\347\250\213.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-2-\345\271\266\345\217\221\347\256\200\347\225\245-\345\244\232\350\277\233\347\250\213.md" index 887f4d7..4fe3993 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-2-\345\271\266\345\217\221\347\256\200\347\225\245-\345\244\232\350\277\233\347\250\213.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-2-\345\271\266\345\217\221\347\256\200\347\225\245-\345\244\232\350\277\233\347\250\213.md" @@ -103,7 +103,7 @@ func main() { } ``` -根据该方式,就可以很容运行计算机上的其他任何程序,包括自身的命令行、Java程序等等。 +根据该方式,就可以很容易运行计算机上的其他任何程序,包括自身的命令行、Java程序等等。 ## 四 进程分类 @@ -112,7 +112,7 @@ func main() { - 用户进程:位于用户空间中,是程序执行的实例 - 内核进程:位于内核空间中,可以访问硬件 -由于用户进程无法访问内核空间,所以无法直接操作硬件。内核会暴露一些接口提供给用户进程使用,让用户进程简介操作硬件,这便是系统调用。 +由于用户进程无法访问内核空间,所以无法直接操作硬件。内核会暴露一些接口提供给用户进程使用,让用户进程间接操作硬件,这便是系统调用。 内核为了保证系统的安全和稳定,为**CPU**特供了两个状态: - 用户态:大部分时间CPU处于该状态,此时只能访问用户空间 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-4-\345\271\266\345\217\221\347\256\200\347\225\245-\351\235\236\351\230\273\345\241\236IO.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-4-\345\271\266\345\217\221\347\256\200\347\225\245-\351\235\236\351\230\273\345\241\236IO.md" index 2802a38..a34868d 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-4-\345\271\266\345\217\221\347\256\200\347\225\245-\351\235\236\351\230\273\345\241\236IO.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-4-\345\271\266\345\217\221\347\256\200\347\225\245-\351\235\236\351\230\273\345\241\236IO.md" @@ -1,6 +1,6 @@ ## 一 深入理解进程阻塞 -进程间的通信时通过 send() 和 receive() 两种基本操作完成的。具体如何实现这两种基础操作,存在着不同的设计: +进程间的通信是通过 send() 和 receive() 两种基本操作完成的。具体如何实现这两种基础操作,存在着不同的设计: > 消息的传递有可能是**阻塞的**或**非阻塞的**,也被称为**同步**或**异步**的。----《操作系统概论》 @@ -16,14 +16,14 @@ - 时钟中断( Clock Interrupt ):一个硬件时钟会每隔一段(很短)的时间就产生一个中断信号发送给 CPU,CPU 在响应这个中断时, 就会去执行操作系统内核的指令, 继而将 CPU 的控制权转移给了操作系统内核, 可以由操作系统内核决定下一个要被执行的指令。 - 系统调用(system call):system call 是操作系统提供给应用程序的接口。 用户通过调用 system call 来完成那些需要操作系统内核进行的操作, 例如硬盘, 网络接口设备的读写等。 -现代操作系统都是采用虚拟存储器。操心系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核,保证内核的安全,操心系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。 +现代操作系统都是采用虚拟存储器。操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核,保证内核的安全,操心系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。 用户进程在从用户空间切换到内核空间,需要以下步骤: - 1.当一个程序正在执行的过程中, 中断(interrupt) 或 系统调用(system call) 发生可以使得 CPU 的控制权会从当前进程转移到操作系统内核。 - 2.操作系统内核负责保存进程i在 CPU 中的上下文(程序计数器,寄存器)到 PCB$_i$(操作系统分配给进程的一个内存块)中 - 3.从PCB$_j$取出进程 j 的CPU 上下文, 将 CPU 控制权转移给进程 j , 开始执行进程 j 的指令。 -操作系统在进行进切换时,需要进行一系列的内存读写操作, 这带来了一定的开销:对于一个运行着 UNIX 系统的现代 PC 来说, 进程切换至少需要花费 300 us 的时间。我们所说的 “阻塞”是指进程在发起了一个系统调用(System Call) 后,由于该系统调用的操作不能立即完成,需要等待一段时间,于是内核将进程挂起为**等待 (waiting)**状态, 以确保它不会被调度执行, 占用 CPU 资源。 +操作系统在进行切换时,需要进行一系列的内存读写操作, 这带来了一定的开销:对于一个运行着 UNIX 系统的现代 PC 来说, 进程切换至少需要花费 300 us 的时间。我们所说的 “阻塞”是指进程在发起了一个系统调用(System Call) 后,由于该系统调用的操作不能立即完成,需要等待一段时间,于是内核将进程挂起为**等待 (waiting)**状态, 以确保它不会被调度执行, 占用 CPU 资源。 综上所述,**阻塞和非阻塞描述的是进程的一个操作是否会使得进程转变为“等待”的状态**,又因为阻塞这个词是与系统调用 System Call 紧紧联系在一起的, 因为要让一个进程进入 等待(waiting) 的状态,要么是它主动调用 wait() 或 sleep() 等挂起自己的操作,要么是它调用 System Call, 而 System Call 因为涉及到了 I/O 操作,不能立即完成,于是内核就会先将该进程置为等待状态,调度其他进程的运行,等到它所请求的 I/O 操作完成了以后,再将其状态更改回 ready 。 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-6-\345\271\266\345\217\221\347\256\200\347\225\245-\345\257\271\346\257\224\345\271\266\345\217\221\346\250\241\345\236\213.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-6-\345\271\266\345\217\221\347\256\200\347\225\245-\345\257\271\346\257\224\345\271\266\345\217\221\346\250\241\345\236\213.md" index 947a0b0..b961e62 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-6-\345\271\266\345\217\221\347\256\200\347\225\245-\345\257\271\346\257\224\345\271\266\345\217\221\346\250\241\345\236\213.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/00-6-\345\271\266\345\217\221\347\256\200\347\225\245-\345\257\271\346\257\224\345\271\266\345\217\221\346\250\241\345\236\213.md" @@ -35,7 +35,7 @@ Goroutines 是在 Golang 中执行并发任务的方式,不过要切记: > Goroutines仅存在于 Go 运行时而不存在于 OS 中,因此需要 Go调度器(GoRuntimeScheduler) 来管理它们的生命周期。 -Go运行时为此维护了三个C结构(https://golang.org/src/runtime/runtime2.go): +Go运行时为此维护了三个C结构(https://go.dev/src/runtime/runtime2.go): - G 结构:表示单个 Goroutine,包含跟踪其堆栈和当前状态所需的对象。还包含自己负责的代码的引用。 - M 结构:表示 OS 线程。包含一些对象指针,例如全局可执行的 Goroutines 队列,当前运行的 Goroutine,它自己的缓存以及对 Go 调度器的引用。 - P 结构:也做Sched结构,它是一个单一的全局对象,用于跟踪 Goroutine 和 M 的不同队列以及调度程序运行时需要的其他一些信息,例如单一全局互斥锁(Global Sched Lock)。 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/01-goroutine.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/01-goroutine.md" index e84ea9e..808f3b6 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/01-goroutine.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/01-goroutine.md" @@ -39,7 +39,7 @@ func main() { fmt.Scanln(&input) } ``` -命令行会不断地输出 tick,同时可以使用 `fmt.Scanln()` 接受用户输入。两个环节可以同时进行,直到按 Enter键时将输入的内容写入 input变量中井返回, +命令行会不断地输出 tick,同时可以使用 `fmt.Scanln()` 接受用户输入。两个环节可以同时进行,直到按 Enter键时将输入的内容写入 input变量中并返回, 整个程序终止。 ### 2.2 一道基础面试题 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/02-channel.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/02-channel.md" index 405f606..48c404f 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/02-channel.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/02-channel.md" @@ -137,8 +137,8 @@ func main() { - 通道的个数为当前实际存储的数据个数 - 缓冲区具备数据存储的能力,到达存储上限后才会阻塞,相当于具备了异步的能力 - 有缓冲channel的阻塞产生条件: - - 带缓冲通道被填满时,尝试再次发送数据会发生阻塞 - - 带缓冲通道为空时,尝试接收数据会发生阻塞 + - 当缓冲通道被填满时,尝试再次发送数据会发生阻塞 + - 当缓冲通道为空时,尝试接收数据会发生阻塞 问题:为什么 Go语言对通道要限制长度而不提供无限长度的通道? -> channel是在两个 goroutine 间通信的桥梁。使用 goroutine 的代码必然有一方提供数据,一方消费数据 。通道如果不限制长度,在生产速度大于消费速度时,内存将不断膨胀直到应用崩溃。 \ No newline at end of file +> channel是在两个 goroutine 间通信的桥梁。使用 goroutine 的代码必然有一方提供数据,一方消费数据 。通道如果不限制长度,在生产速度大于消费速度时,内存将不断膨胀直到应用崩溃。 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/04-channel\347\232\204\345\272\224\347\224\250.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/04-channel\347\232\204\345\272\224\347\224\250.md" index fb700e8..12010a6 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/04-channel\347\232\204\345\272\224\347\224\250.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/04-channel\347\232\204\345\272\224\347\224\250.md" @@ -99,7 +99,7 @@ type Timer struct { ```go // 创建定时器 定义延迟时间为2秒 layTimer := time.NewTimer(time.Second * 2) - // 从管道取数据,但是一直都是空的,阻塞中,直到2庙后有数据才能取出 + // 从管道取数据,但是一直都是空的,阻塞中,直到2秒后有数据才能取出 fmt.Println(<-layTimer.C) ``` diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/05-select.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/05-select.md" index 23cdb03..0d070aa 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/05-select.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/05-select.md" @@ -58,7 +58,7 @@ select支持default,如果select没有一条语句可以执行,即所有的 注意:select中的case必须是I/O操作。 -#### 2.3 channel超时解决 +#### 2.2 channel超时解决 在并发编程的通信过程中,最需要处理的是超时问题,即向channel写数据时发现channel已满,或者取数据时发现channel为空,如果不正确处理这些情况,会导致goroutine锁死,例如: ```go @@ -81,7 +81,7 @@ i := <-ch } ``` -#### 2.4 空select +#### 2.3 空select 空的select唯一的功能是阻塞代码: ```go diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/06-Go\345\215\217\347\250\213\350\260\203\345\272\246\346\250\241\345\236\213-1.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/06-Go\345\215\217\347\250\213\350\260\203\345\272\246\346\250\241\345\236\213-1.md" index aa16555..ce9ee5f 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/06-Go\345\215\217\347\250\213\350\260\203\345\272\246\346\250\241\345\236\213-1.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/06-Go\345\215\217\347\250\213\350\260\203\345\272\246\346\250\241\345\236\213-1.md" @@ -7,7 +7,7 @@ Go的著名主张: > 不要用共享内存的方式来通信,应该以通信作为手段来共享内存 -Go推荐使用通道(channel)的方式解决数据传递问题,在多个goroutine之间,channel复杂传递数据,还能保证整个过程的并发安全性。 +Go推荐使用通道(channel)的方式解决数据传递问题,在多个goroutine之间,channel负责传递数据,还能保证整个过程的并发安全性。 当然Go也依然提供了传统的同步方法,如互斥量,条件变量等。 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2452-\347\255\211\345\276\205\347\273\204.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2452-\347\255\211\345\276\205\347\273\204.md" index 1d54c22..ade2149 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2452-\347\255\211\345\276\205\347\273\204.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2452-\347\255\211\345\276\205\347\273\204.md" @@ -1,6 +1,6 @@ ## 一 等待组 sync.WaitGroup - `sync.WaitGroup`类型的值也是并发安全的,该类型结构体中内内部拥有一个计数器,计数器的值可以通过方法调用实现计数器的增加和减少 。 + `sync.WaitGroup`类型的值也是并发安全的,该类型结构体中内部拥有一个计数器,计数器的值可以通过方法调用实现计数器的增加和减少 。 当我们添加了 N 个并发任务进行工作时,就将等待组的计数器值增加 N。每个任务完成时,这个值减1。 同时,在另外一个 goroutine 中等待这个等待组的计数器值为 0 时, 表示所有任务己经完成。 diff --git "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2455-\345\216\237\345\255\220\346\223\215\344\275\234.md" "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2455-\345\216\237\345\255\220\346\223\215\344\275\234.md" index eb73c68..9ffe629 100644 --- "a/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2455-\345\216\237\345\255\220\346\223\215\344\275\234.md" +++ "b/02-\345\271\266\345\217\221\347\274\226\347\250\213/08-\345\220\214\346\255\2455-\345\216\237\345\255\220\346\223\215\344\275\234.md" @@ -76,7 +76,7 @@ Go的`sync/atomic`包提供的存储函数都是以`Store`为前缀。 示例: ```go -// 参数一位被操作数据的指针 参数二是要存储的新值 +// 参数一为被操作数据的指针 参数二是要存储的新值 atomic.StoreInt32(i *int3, v int32) ``` diff --git "a/04-Web\347\274\226\347\250\213/02-ServeMux\344\270\216\344\270\255\351\227\264\344\273\266.md" "b/04-Web\347\274\226\347\250\213/02-ServeMux\344\270\216\344\270\255\351\227\264\344\273\266.md" index d652996..668b5da 100644 --- "a/04-Web\347\274\226\347\250\213/02-ServeMux\344\270\216\344\270\255\351\227\264\344\273\266.md" +++ "b/04-Web\347\274\226\347\250\213/02-ServeMux\344\270\216\344\270\255\351\227\264\344\273\266.md" @@ -3,7 +3,7 @@ 在golang的web开发中,一个handler响应一个http请求: ```go type Handler interface{ - ServerHTTP(ResponseWriter, *Request) + ServeHTTP(ResponseWriter, *Request) } ``` @@ -140,4 +140,4 @@ func main() { } -``` \ No newline at end of file +``` diff --git "a/06-\345\276\256\346\234\215\345\212\241/02-protobuf-1-\346\246\202\350\277\260\344\270\216\345\256\211\350\243\205.md" "b/06-\345\276\256\346\234\215\345\212\241/02-protobuf-1-\346\246\202\350\277\260\344\270\216\345\256\211\350\243\205.md" index 36b62c8..d9b51dc 100644 --- "a/06-\345\276\256\346\234\215\345\212\241/02-protobuf-1-\346\246\202\350\277\260\344\270\216\345\256\211\350\243\205.md" +++ "b/06-\345\276\256\346\234\215\345\212\241/02-protobuf-1-\346\246\202\350\277\260\344\270\216\345\256\211\350\243\205.md" @@ -15,7 +15,7 @@ protobuf优点: - 1:序列化后体积相比Json和XML很小,适合网络传输 - 2:支持跨平台多语言 - 3:消息格式升级和兼容性还不错 -- 4:序列化反序列化速度很快,快于Json的处理速速 +- 4:序列化反序列化速度很快,快于Json的处理速度 protobuf也有其不可忽视的缺点: - 功能简单,无法用来表示复杂的概念。 diff --git "a/06-\345\276\256\346\234\215\345\212\241/02-protobuf-2-\350\257\255\346\263\225\344\270\216\345\216\237\347\220\206.md" "b/06-\345\276\256\346\234\215\345\212\241/02-protobuf-2-\350\257\255\346\263\225\344\270\216\345\216\237\347\220\206.md" index c3271d7..910f040 100644 --- "a/06-\345\276\256\346\234\215\345\212\241/02-protobuf-2-\350\257\255\346\263\225\344\270\216\345\216\237\347\220\206.md" +++ "b/06-\345\276\256\346\234\215\345\212\241/02-protobuf-2-\350\257\255\346\263\225\344\270\216\345\216\237\347\220\206.md" @@ -52,7 +52,7 @@ message Person { ``` #### 2.4 枚举类型 -比如电话号码,只有移动电话、家庭电话、工作电话三种,因此枚举作为选项,如果没设置的话枚举类型的默认值为第一项。在上面的例子中在个人message中加入电话号码这个Filed。如果枚举类型中有不同的名字对应相同的数字id,需要加入option allow_alias = true这一项,否则会报错。枚举类型中也有reserverd Filed和number,定义和message中一样。 +比如电话号码,只有移动电话、家庭电话、工作电话三种,因此枚举作为选项,如果没设置的话枚举类型的默认值为第一项。在下面的例子中在个人message中加入电话号码这个Filed。如果枚举类型中有不同的名字对应相同的数字id,需要加入option allow_alias = true这一项,否则会报错。枚举类型中也有reserverd Filed和number,定义和message中一样。 ``` message Person { required string name = 1; @@ -170,4 +170,4 @@ message Test { 如果用int32来保存一个负数,结果总是有10个字节长度,被看做是一个非常大的无符号整数。使用有符号类型会更高效。它使用一种ZigZag的方式进行编码。即-1编码成1,1编码成2,-2编码成3这种形式。 -也就是说,对于sint32来说,n编码成 (n << 1) ^ (n >> 31),注意到第二个移位是算法移位。 \ No newline at end of file +也就是说,对于sint32来说,n编码成 (n << 1) ^ (n >> 31),注意到第二个移位是算法移位。 diff --git "a/06-\345\276\256\346\234\215\345\212\241/03-rpc-3-grpc\344\270\216go\345\256\236\347\216\260.md" "b/06-\345\276\256\346\234\215\345\212\241/03-rpc-3-grpc\344\270\216go\345\256\236\347\216\260.md" index dfc0d4c..edb786b 100644 --- "a/06-\345\276\256\346\234\215\345\212\241/03-rpc-3-grpc\344\270\216go\345\256\236\347\216\260.md" +++ "b/06-\345\276\256\346\234\215\345\212\241/03-rpc-3-grpc\344\270\216go\345\256\236\347\216\260.md" @@ -60,7 +60,7 @@ package main import ( "fmt" - "golang.org/x/net/context" + "context" "google.golang.org/grpc" "net" pb "test/protoes" @@ -118,7 +118,7 @@ package main import ( "fmt" - "golang.org/x/net/context" + "context" "google.golang.org/grpc" pb "test/protoes" ) @@ -176,4 +176,4 @@ go run client.go ``` SayHi 响应: message:"Hi Kitty" GetMsg 响应: msg:"Server msg is coming..." -``` \ No newline at end of file +``` diff --git "a/06-\345\276\256\346\234\215\345\212\241/04-\346\234\215\345\212\241\345\217\221\347\216\260.md" "b/06-\345\276\256\346\234\215\345\212\241/04-\346\234\215\345\212\241\345\217\221\347\216\260.md" index 6add052..dd2b2b0 100644 --- "a/06-\345\276\256\346\234\215\345\212\241/04-\346\234\215\345\212\241\345\217\221\347\216\260.md" +++ "b/06-\345\276\256\346\234\215\345\212\241/04-\346\234\215\345\212\241\345\217\221\347\216\260.md" @@ -83,6 +83,6 @@ #### 2.8 其他 -Java著名微服务架构体系SpringCloud对上述四者都提供了集成,但对Cponsul支持较为完善。 +Java著名微服务架构体系SpringCloud对上述四者都提供了集成,但对Consul支持较为完善。 -参考地址:http://dockone.io/article/667 \ No newline at end of file +参考地址:http://dockone.io/article/667 diff --git "a/07-\346\240\207\345\207\206\345\272\223/io.md" "b/07-\346\240\207\345\207\206\345\272\223/io.md" index 4c7c2f4..466a668 100644 --- "a/07-\346\240\207\345\207\206\345\272\223/io.md" +++ "b/07-\346\240\207\345\207\206\345\272\223/io.md" @@ -173,7 +173,7 @@ func main() { reader := bufio.NewReader(file) for { str, err := reader.ReadString("\n") //读到换行就结束一次 - if err != io.EOF { //io.EOF表示问价末尾 + if err == io.EOF { //io.EOF表示问价末尾 break } //输出内容 @@ -189,4 +189,4 @@ if err != nil { fmt.Printf("%v",err) } fmt.Prinf("%v",string(content)) -``` \ No newline at end of file +``` diff --git a/README.md b/README.md index 683a2f9..d42d11f 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,55 @@ +# README + ## 一 笔记说明 这份笔记是自学`Golang`时的资料总结,结合了很多书籍、博客以及开源作品的内容,同时也收到了很多反馈和建议,笔记仍然会在学习旅程中不断更新,绝对不鸽。 -基于Go的算法笔记一样计划之列,不过算法过于庞大,被独立放置在了[overnote](https://github.com/overnote/over-algorithm)系列中自成一系。 +基于 Go 的算法笔记一样计划之列,不过算法过于庞大,被独立放置在了[overnote](https://github.com/overnote/over-algorithm)系列中自成一系。 + +## 二 Go 学习路径图 + +![Go 学习路径图](./images/go/go-develep.png) + +## 三 Go 相关书籍 + +语法: -## 二 Go学习路径图 +- [《Go 程序设计语言》](https://book.douban.com/subject/27044219/):Go 语言圣经,[中译资料](https://github.com/gopl-zh/gopl-zh.github.com) +- [《Go 语言趣学指南》](https://book.douban.com/subject/34951096/):极简入门 +- [《Learning Go》](https://book.douban.com/subject/35128336/) -![](./images/go/go-develep.png) +实战: -## 三 Go相关书籍 +- [《Go 语言编程之旅:一起用 Go 做项目》](https://book.douban.com/subject/) -- [《Go程序设计语言》](https://book.douban.com/subject/27044219/):Go语言圣经,[中译资料](https://github.com/gopl-zh/gopl-zh.github.com) -- [《GoWeb编程》](https://book.douban.com/subject/27204133/):Go语言Web编程基础 -- [《Go并发编程实战》](https://book.douban.com/subject/27016236/):非常好的go并发原理解读书籍,但语言组织欠佳 -- [《Go语言学习笔记》](https://book.douban.com/subject/26832468/):言简意赅,深入浅出,力荐 -- [《Go语言高级编程》](https://book.douban.com/subject/34442131/):深入理解Go必备,[开源文档](https://github.com/chai2010/advanced-go-programming-book) +深入: + +- [《Go 并发编程实战》](https://book.douban.com/subject/27016236/):非常好的 go 并发原理解读书籍,但语言组织欠佳 +- [《Go 专家编程》](https://book.douban.com/subject/35144587/) +- [《Go 语言精进之路》](https://book.douban.com/subject/35720728/) +- [《Go 语言学习笔记》](https://book.douban.com/subject/26832468/):言简意赅,深入浅出,力荐 +- [《Go 语言高级编程》](https://book.douban.com/subject/34442131/):深入理解 Go 必备,[开源文档](https://github.com/chai2010/advanced-go-programming-book) + +仍然处于试看阶段书籍: + +- [《Go 语言底层原理剖析》](https://book.douban.com/subject/35556889/):试看中 +- [《Go 语言设计与实现》](https://book.douban.com/subject/35635836/):试看中 +- [《精通 Go 语言(第 2 版)》](https://item.jd.com/13543938.html#none):试看中 + 35130972/):试看中 +- [《GO 微服务实战》](https://book.douban.com/subject/35381916/):试看中 +- [《Go 语言从基础到中台微服务实战开发》](https://item.jd.com/10034293424182.html):试看中 +- [《深入学习 Go 语言》](https://book.douban.com/subject/34798021/) ## 附录:笔记汇总 -**OverNote**地址:https://github.com/overnote -**笔者的地址**:https://github.com/ruyuejun +**OverNote**地址: +**笔者的地址**: -**OverNote分类**: -- [Golang](https://github.com/overnote/over-golang):详尽的Go领域笔记:Go语法、Go并发编程、GoWeb编程、Go微服务等 -- [大前端](https://github.com/overnote/over-javascript):包含JavaScript、Node.js、vue/react、微信开发、Flutter等大前端技术 -- [数据结构与算法](https://github.com/overnote/over-algorithm):以C/Go实现为主记录数据结构与算法的笔记 -- [服务端架构](https://github.com/overnote/over-server):分布式与微服务笔记,附Nginx、Mysql、Redis等常用服务端技术 +**OverNote 分类**: + +- [Golang](https://github.com/overnote/over-golang):详尽的 Go 领域笔记:Go 语法、Go 并发编程、GoWeb 编程、Go 微服务等 +- [大前端](https://github.com/overnote/over-javascript):包含 JavaScript、Node.js、vue/react、微信开发、Flutter 等大前端技术 +- [数据结构与算法](https://github.com/overnote/over-algorithm):以 C/Go 实现为主记录数据结构与算法的笔记 +- [服务端架构](https://github.com/overnote/over-server):分布式与微服务笔记,附 Nginx、Mysql、Redis 等常用服务端技术 - [Linux](https://github.com/overnote/over-linux):计算机组成原理、操作系统、计算机网络、编译原理基础学科笔记 - [大数据](https://github.com/overnote/over-bigdata):大数据笔记,完善中 -- [Python与机器学习](https://github.com/overnote/over-python):Python相关笔记,完善中 - +- [Python 与机器学习](https://github.com/overnote/over-python):Python 相关笔记,完善中