May 19, 2021
Golang进阶笔记 # 路径问题 # test_test.go # package main import "testing" func TestHelloWorld(t *testing.T) { // t.Fatal("not implemented") path := getCurrentPath() t.Log("getCurrentPath: ", path) } test.go # package main import ( "fmt" "log" "os" "path" "path/filepath" "runtime" "strings" ) func main() { fmt.Println("getTmpDir(当前系统临时目录) = ", getTmpDir()) fmt.Println("getCurrentAbPathByExecutable(仅支持go build) = ", getCurrentAbPathByExecutable()) fmt.Println("getCurrentAbPathByCaller(仅支持go run) = ", getCurrentAbPathByCaller()) fmt.Println("getCurrentAbPath(最终方案-全兼容) = ", getCurrentAbPath()) fmt.Println("getCurrentPath(runtime.Caller1) = ", getCurrentPath()) } // 最终方案-全兼容 func getCurrentAbPath() string { dir := getCurrentAbPathByExecutable() if strings.
...
May 19, 2021
Golang进阶笔记 # 路径问题 # test_test.go # package main import "testing" func TestHelloWorld(t *testing.T) { // t.Fatal("not implemented") path := getCurrentPath() t.Log("getCurrentPath: ", path) } test.go # package main import ( "fmt" "log" "os" "path" "path/filepath" "runtime" "strings" ) func main() { fmt.Println("getTmpDir(当前系统临时目录) = ", getTmpDir()) fmt.Println("getCurrentAbPathByExecutable(仅支持go build) = ", getCurrentAbPathByExecutable()) fmt.Println("getCurrentAbPathByCaller(仅支持go run) = ", getCurrentAbPathByCaller()) fmt.Println("getCurrentAbPath(最终方案-全兼容) = ", getCurrentAbPath()) fmt.Println("getCurrentPath(runtime.Caller1) = ", getCurrentPath()) } // 最终方案-全兼容 func getCurrentAbPath() string { dir := getCurrentAbPathByExecutable() if strings.
...
May 15, 2018
Golang笔记 # 先贴一个客观的教程文档网站http://www.runoob.com/go/go-slice.html
垃圾回收 # 常见的回收算法 # 引用计数 优点:对象可以被很快回收 缺点:不太好处理循环引用 标记-清除 优点:解决了引用计数的缺点 缺点:需要 STW(Stop The World),暂时停止程序运行 分代收集(按照对象生命周期长短划分不同的代空间,生命周期长的放入老年代,段的放入新生代,不同代有不同的回收算法和回收频率) 优点:回收性能好 缺点:算法复杂 三色标记法(初始状态:白色、从根节点开始遍历,遍历到的变成灰色,遍历灰色,将灰色引用的标记灰色,遍历过的灰色对象变为黑色。循环遍历灰色对象。通过写屏障检测对象的变化,重复。收集所有白色对象(垃圾)) GPM调度和CSP模型 # CSP 模型? # CSP 模型是“以通信的方式来共享内存”,不同于传统的多线程通 过共享内存来通信。用于描述两个独立的并发实体通过共享的通 讯 channel (管道)进行通信的并发模型。
GPM 分别是什么、分别有多少数量? # • G(Goroutine): 即Go协程,每个go关键字都会创建一个协 程。 • M(Machine):工作线程,在Go中称为Machine,数量对应真 实的CPU数(真正干活的对象)。 • P(Processor): 处理器(Go中定义的一个摡念,非CPU), 包含运行Go代码的必要资源,用来调度 G 和 M 之间的关联关 系,其数量可通过 GOMAXPROCS() 来设置,默认为核心数。 M必须拥有P才可以执行G中的代码,P含有一个包含多个G的队 列,P可以调度G交由M执行。
Goroutine调度策略 # • 队列轮转:P 会周期性的将G调度到M中执行,执行一段时间 后,保存上下文,将G放到队列尾部,然后从队列中再取出一个 G进行调度。除此之外,P还会周期性的查看全局队列是否有G等 待调度到M中执行。 • 系统调用:当G0即将进入系统调用时,M0将释放P,进而某个空 闲的M1获取P,继续执行P队列中剩下的G。M1的来源有可能是 M的缓存池,也可能是新建的。 当G0系统调用结束后,如果有空闲的P,则获取一个P,继续执 行G0。如果没有,则将G0放入全局队列,等待被其他的P调度。 然后M0将进入缓存池睡眠。 !
...
May 15, 2018
Golang笔记 # 先贴一个客观的教程文档网站http://www.runoob.com/go/go-slice.html
并发 Channel # 使用关键字go开启goroutine 轻量级线程
go fun_name(paras_list) # eg: go f(x, y, z) 代码
package main import ( "fmt" "time" ) func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") say("hello") } Channel # 用于传递数据的数据结构 可用于两个goroutine之间传递指定类型值,同步和通讯 <- 指定通道方向(发送or接受),未指定则双向通道
声明通道 # 使用chan关键字, 在使用之前,需先创建.
ch := make(chan int) 示例
package main import "fmt" func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum // 把 sum 发送到通道 c } func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c // 从通道 c 中接收 fmt.
...