go语言栈结构 go的栈

Go语言的跨平台能力到底有多强?看完你就知道了对比于其他语言的程序,Go语言的跨平台能力是真的强 , 拿.Net和JAVA来说吧,.Net在.Net core出现之前是不能跨平台的,只能在windows上编译运行,即使是.net core出现以后 , 跨平台的程序也是相当的麻烦 。而java虽然一直都可以跨平台,但是运行JAVA程序的机器上也必须要有JAVA程序运行环境JRE 。而相对于Go程序,跨平台就简单的多了,只需要在编译指定目标程序运行的架构和环境即可编译出指定操作系统和架构的程序 。
以上是指定了go的环境变量后执行的go build命令进行目标程序的构建,这种方式会一直生效的,如果不让他一直生效,可以在构建的时候临时指定环境变量,下面以window的环境为例,来介绍临时指定环境变量的方式构建可以在Linux环境下运行的可执行程序:
可以根据不同的架构和操作系统将其编写为不同的.bat的可执行文件放置在程序的根目录,Linux的和MAC的也一样编写成脚本文件放置在程序的根目录,这样在构建的时候就不用再敲命令了,直接运行脚本就可以了 。
Java程序编译打包后为war包或者是java包 , 必须执行java -jar 命令或者将其放置到tomcat的指定目录下,运行tomcat程序 。而Go语言编写的程序最终为可执行的文件(window下编译出的是.exe的可执行文件),只需要将其赋予可执行的权限就可以直接运行了 。
构建JAVA程序的镜像需要指定java的基础镜像,否则就需要在镜像中安装java的运行环境了,下面展示的是构建的一个JAVA程序的镜像 , 构建出来镜像的体积相对比较大
而Go程序制作出的镜像就不需要安装任何的依赖环境,因为他在打包的时候就已经将依赖的包一块打包到一起了
拿着这个镜像就可以到处运行了 。
通过对比我们可以发现,如果没有之前的技术和业务的积累,重新开发一个新的项目,使用go去开发无疑是最容易上手的,所以现在很多公司都使用go进行开发,也逐渐将其他语言的项目逐步的用go语言进行改造 。其实用什么语言不重要 , 合适的才重要,开发项目在选择语言的时候也会综合多方面来考虑选择合适的语言和架构,毕竟很多公司都不是搞研究的,都需要项目来赚钱 , 所以开发的速度、客户的满意度、项目交付的时间才是驱动公司技术的主要因素 。
我们个人也应该不断完善自己的技术栈,不应该太依靠某种语言,最重要的还是自己的架构思想和底层架构知识,只有掌握了这些才能够不被 社会 和公司“优化” 。
Golang数据结构与算法全能战士今天给大家推荐是由Social Explorer团队开源的gods框架 , 自称"上帝",听这个名字就很霸气,正确的解释是GoDS(Go Data Structures),是数据结构与算法相关的框架 。
全能战士,该框架覆盖了数据结构与算法里,大部分容器、集合类的实现 , 比golang 的标准开发包提供更丰富的数据结构 。
在Go中实现各种数据结构和算法 。
吸取了其他算法库数十年的知识和经验 。
通过针对给定的一组问题使用最佳算法和数据结构来避免消耗内存,例如,在TreeMap的情况下,红黑树避免在内存中保留冗余排序的键数组 。
结构良好的库,具有简单的原子操作集 , 胜任复杂的数据操作 。
保持库向后兼容
可参考的例子非常多
可以方便集成到产品中.
没有额外的导入.当实现算法的时候,我们通常要在时间效率与内存消耗之间权衡,我们选择在内存首先的情况下,不断优化得到最好的时间效率;线程安全不是重点 , 应该在更高的应用层上处理 。
囊括了列表,栈,图,树等基本数据结构 , 集合实现了HashSet, TreeSet, LinkedHashSet,列表实现ArrayList, SinglyLinkedList, DoublyLinkedList,对栈实现LinkedListStack, ArrayStack,图实现了HashMap, TreeMap, HashBidiMap, TreeBidiMap, LinkedHashMap,树实现了RedBlackTree, AVLTree, BTree,BinaryHeap,都经过性能测试的考验,值得信赖 。
对于Golang开发而言 , gods对底层数据结构做很好的封装,Social Explorer团队在数据处理领域,数据可视化领域有极具竞争力的产品,相信在数据处理领域有很深的积淀,才创造这么优秀的框架,由于篇幅限制 , 相关图片展示效果不好,感兴趣的上官网去看看 。
官网:
GitHub
希望大家能从emirpasic/gods学到有价值的东西 。
愿我们在Go 语言的学习之路上从此结伴而行
go程序如何分配堆栈的在Go语言中有一些调试技巧能帮助我们快速找到问题,有时候你想尽可能多的记录异常但仍觉得不够 , 搞清楚堆栈的意义有助于定位Bug或者记录更完整的信息 。
本文将讨论堆栈跟踪信息以及如何在堆栈中识别函数所传递的参数 。
Functions
先从这段代码开始:
Listing 1
01 package main
02
03 func main() {
04slice := make([]string, 2, 4)
05Example(slice, "hello", 10)
06 }
07
08 func Example(slice []string, str string, i int) {
09panic("Want stack trace")
10 }
Example函数定义了3个参数,1个string类型的slice, 1个string和1个integer, 并且抛出了panic,运行这段代码可以看到这样的结果:
Listing 2
Panic: Want stack trace
goroutine 1 [running]:
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:90x64
main.main()
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:50x85
goroutine 2 [runnable]:
runtime.forcegchelper()
/Users/bill/go/src/runtime/proc.go:90
runtime.goexit()
/Users/bill/go/src/runtime/asm_amd64.s:22320x1
goroutine 3 [runnable]:
runtime.bgsweep()
/Users/bill/go/src/runtime/mgc0.go:82
runtime.goexit()
/Users/bill/go/src/runtime/asm_amd64.s:22320x1
堆栈信息中显示了在panic抛出这个时间所有的goroutines状态,发生的panic的goroutine会显示在最上面 。
Listing 3
01 goroutine 1 [running]:
02 main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:90x64
03 main.main()
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:50x85
第1行显示最先发出panic的是goroutine 1, 第二行显示panic位于main.Example中, 并能定位到该行代码,在本例中第9行引发了panic 。
下面我们关注参数是如何传递的:
Listing 4
// Declaration
main.Example(slice []string, str string, i int)
// Call to Example by main.
slice := make([]string, 2, 4)
Example(slice, "hello", 10)
// Stack trace
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
这里展示了在main中带参数调用Example函数时的堆栈信息,比较就能发现两者的参数数量并不相同,Example定义了3个参数,堆栈中显示了6个参数 。现在的关键问题是我们要弄清楚它们是如何匹配的 。
第1个参数是string类型的slice,我们知道在Go语言中slice是引用类型,即slice变量结构会包含三个部分:指针、长度(Lengthe)、容量(Capacity)
Listing 5
// Slice parameter value
slice := make([]string, 2, 4)
// Slice header values
Pointer:0x2080c3f50
Length:0x2
Capacity: 0x4
// Declaration
main.Example(slice []string, str string, i int)
// Stack trace
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
因此,前面3个参数会匹配slice,如下图所示:
Figure 1
figure provided by Georgi Knox
我们现在来看第二个参数 , 它是string类型,string类型也是引用类型,它包括两部分:指针、长度 。
Listing 6
// String parameter value
"hello"
// String header values
Pointer: 0x425c0
Length:0x5
// Declaration
main.Example(slice []string, str string, i int)
// Stack trace
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
可以确定,堆栈信息中第4、5两个参数对应代码中的string参数,如下图所示:
Figure 2
figure provided by Georgi Knox
最后一个参数integer是single word值 。
Listing 7
// Integer parameter value
10
// Integer value
Base 16: 0xa
// Declaration
main.Example(slice []string, str string, i int)
// Stack trace
main.Example(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
现在我们可以匹配代码中的参数到堆栈信息了 。
Figure 3
figure provided by Georgi Knox
Methods
如果我们将Example作为结构体的方法会怎么样呢?
Listing 8
01 package main
02
03 import "fmt"
04
05 type trace struct{}
06
07 func main() {
08slice := make([]string, 2, 4)
09
10var t trace
11t.Example(slice, "hello", 10)
12 }
13
14 func (t *trace) Example(slice []string, str string, i int) {
15fmt.Printf("Receiver Address: %p\n", t)
16panic("Want stack trace")
17 }
如上所示修改代码 , 将Example定义为trace的方法,并通过trace的实例t来调用Example 。
再次运行程序,会发现堆栈信息有一点不同:
Listing 9
Receiver Address: 0x1553a8
panic: Want stack trace
01 goroutine 1 [running]:
02 main.(*trace).Example(0x1553a8, 0x2081b7f50, 0x2, 0x4, 0xdc1d0, 0x5, 0xa)
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:160x116
03 main.main()
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:110xae
首先注意第2行的方法调用使用了pointer receiver,在package名字和方法名之间多出了"*trace"字样 。另外,参数列表的第1个参数标明了结构体(t)地址 。我们从堆栈信息中看到了内部实现细节 。
Packing
如果有多个参数可以填充到一个single word, 则这些参数值会合并打包:
Listing 10
01 package main
02
03 func main() {
04Example(true, false, true, 25)
05 }
06
07 func Example(b1, b2, b3 bool, i uint8) {
08panic("Want stack trace")
09 }
这个例子修改Example函数为4个参数:3个bool型和1个八位无符号整型 。bool值也是用8个bit表示 , 所以在32位和64位架构下,4个参数可以合并为一个single word 。
Listing 11
01 goroutine 1 [running]:
02 main.Example(0x19010001)
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:80x64
03 main.main()
/Users/bill/Spaces/Go/Projects/src/github.com/goinaction/code/
temp/main.go:40x32
这是本例的堆栈信息,看下图的具体分析:
Listing 12
// Parameter values
true, false, true, 25
// Word value
BitsBinaryHexValue
00-070000 000101true
08-150000 000000false
【go语言栈结构 go的栈】16-230000 000101true
24-310001 10011925
// Declaration
main.Example(b1, b2, b3 bool, i uint8)
// Stack trace
main.Example(0x19010001)
以上展示了参数值是如何匹配到4个参数的 。当我们看到堆栈信息中包括十六进制值,需要知道这些值是如何传递的 。
关于go语言栈结构和go的栈的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息 , 记得收藏关注本站 。

    推荐阅读