golang 特点
- 开发效率
- 不像java c c++需要遍历整个依赖连中所有依赖的库,只关注直接被引用的库,所以编译速度很快
- 动态,克服了python的动态弱点
- 并发
- goroutine与main线程,其他goroutine并行执行
- goroutine之间通过channel通信,避免使用共享内存,共享内存在高并发下很容易出现数据被篡改的情况,在使用锁的情况下,则会出现性能下降
- 大白话版本:其实也就是让数据在channel中通过"流动"来共享,而不是让数据在一个地方,然后让线程们都去同一个地方去访问,大家都去同一个地方,肯定就拥挤了(是不是和火车站人流原理类似啊,进的和出的是两条不会交互的路)
- channel之间传递数据不需要锁和等待同步
- 类型系统
- 摒弃oop的集成,采用组合,只需要通过type的嵌套即可实现更复杂的结构,最大程度复用代码
- 通过实现接口interface来对行为进行建模,不需要复杂继承类
- 一个类型实现了一个接口的所有方法,则这个类型实例可以存储在这个接口类型的实例中
- gc让开发更简单
golang基础
-
main函数必须在main包内,否则不会生成可执行文件
-
包的名字承担了明明空间的作用,用于间接访问包内的声明的标识符
-
同一个文件夹下的所有代码文件,必须是同一个报名(太好了,比python的混乱好多了)
-
import的包名前面的下划线 _ 用于对包做初始化操作,调用包中的init函数,不使用包内的标识符(因为go不允许声明导入某个包去不使用)
-
每个代码文件中的init函数都会在在main函数之前被调用
-
没有定义在函数内部的变量,是包级变量,这个包内可访问
-
大写开头的变量,函数是公有的,否则是私有的
-
变量零值
- 数值: 0
- 字符串: “”
- bool: false
- 指针: nil
-
sync.waitGroup用于防止在所有goroutine执行完毕之前程序结束
-
每启动一个goroutine就让waitGroup自增一次,goroutine执行完毕后自减,当值递减到0的时候,就知道所有的goroutine都执行完毕了
-
for _, feed := range feeds
,range在迭代slice
的时候,返回index
,copy
,如果不需要index
就用_
替代 -
map查找,
matcher, exists := matchers[feed.Type]
,如果查找到,第二个返回值则为true,否则为false -
在
for range
循环中,启动匿名函数goroutine,用于并发独立处理数据-
for _, feed := range feeds { // Retrieve a matcher for the search. matcher, exists := matchers[feed.Type] if !exists { matcher = matchers["default"] } // Launch the goroutine to perform the search. go func(matcher Matcher, feed *Feed) { Match(matcher, feed, searchTerm, results) waitGroup.Done() }(matcher, feed) }
-
-
go中,所有的变量都采用值传递,使用指针变量的时候,其实是传递的指针变量的地址值,所以仍然视为值传递
-
waitGroup.Done()
会将waitGroup
的值自减1,表示当前这个goroutine已经执行完毕 -
goroutine阻塞
-
通过在匿名函数中添加
waitGroup.Wait()
使得当前goroutine等待所有goroutine执行完毕,然后才会执行Display -
// Launch a goroutine to monitor when all the work is done. go func() { // Wait for everything to be processed. waitGroup.Wait() // Close the channel to signal to the Display // function that we can exit the program. close(results) }() // Start displaying results as they are available and // return after the final result is displayed. Display(results)
-
-
defer
- defer在函数执行完毕和函数崩溃的时候执行,保证资源的释放
- 同时提高了可读性,防止忘记释放资源
-
Decode中,interface{}配合reflect反射包来实现
-
声明的interface包含了一系列的函数签名
- 自定义的类型,需要实现接口中声明的所有的方法来实现该接口(相同的函数签名)
包管理
- 所有文件都应该在第一行声明自己的包名
- 一个目录下只能时同一个包
- 导入包使用全路径,用去区分同名的不同包
- go get会递归查找所有依赖,并全部下载下来
- 不可引入但不使用包,会导致二进制文件很大和代码臃肿(C语言情况)
- 每个包可以包含多个init函数,并且在main函数之前调用