【Go语言】动态库和静态库详解
【Go语言】动态库和静态库详解
- 前言
- 示例工程
- pkg
- src
- src/calc/calc.go
- src/calc/calc/fibonacci/fibonacci.go
- src/simplemath/add.go
- src/simplemath/sqrt.go
- 一键编译
- gc编译静态库
- gccgo编译静态库
- gccgo编译动态库
- 总结
前言
首先,引用七牛云存储团队在《Go语言编程》的观点(第7章,第9节):
就目前而言,以二进制方式分发Go包并不是很现实。由于Go语言对于兼容性控制的非常严格,任何一个版本号的不同都将导致无法链接包。因此,如果你使用Go语言开发了一个库,那么最合适的库分发方式是直接打包源代码包并进行分发,由使用者自行编译。
但是,笔者认为Go语言的编译和C语言一样,有汇编、链接阶段。所以,有必要了解、学习Go语言的动态库和静态库,也有助于以后分发包。
示例工程
一个标准的Golang工程包含3个目录
- bin 放可执行文件
- pkg 放静态库
- src 放源代码
[user@host goprj]$ ls
bin pkg src
[user@host goprj]$ tree
.
├── bin
├── pkg
│ ├── gccgo_linux_amd64
│ └── linux_amd64
└── src├── calc│ ├── fibonacci│ │ ├── fibonacci.go│ │ └── fibonacci_test.go│ └── calc.go└── simplemath├── add.go└── sqrt.go6 directories, 5 files
[user@host goprj]$
pkg
等下我既使用google的gc工具链,也使用gnu的gccgo工具链,所以pkg下面有两个文件夹
- gccgo_linux_amd64 放gccgo生成的静态库
- linux_amd64 放gc生成的静态库
src
代码有2个包和1个可执行文件
- calc 主程序
- calc/fibonacci 提供斐波那契数相关函数
- simplemath 提供基础的数学运算
src/calc/calc.go
package mainimport "fmt"
import "calc/fibonacci"func main() {var res int64var err errorres, err = fibonacci.Fibonacci(30)if err != nil {panic(err.Error())} else {fmt.Println("Result:", res)}res, err = fibonacci.Fibonacci_r(30)if err != nil {panic(err.Error())} else {fmt.Println("Result:", res)}
}
src/calc/calc/fibonacci/fibonacci.go
package fibonacciimport "simplemath"
import "errors"func Fibonacci(n int64) (int64, error) {if n < 1 {err := errors.New("Should be greater than 0!")return 0, err} else if n > 92 {err := errors.New("Should be less than 93!")return 0, err}var res int64 = 0var tmp int64 = 1var idx int64 = 0for ; idx < n; idx++ {res = simplemath.Add(res, tmp)res, tmp = tmp, res}return res, nil
}func Fibonacci_r(n int64) (int64, error) {if n < 1 {err := errors.New("Should be greater than 0!")return 0, err} else if n < 3 {return 1, nil} else if n > 92 {err := errors.New("Should be less than 93!")return 0, err}lhs, _ := Fibonacci_r(n - 1)rhs, _ := Fibonacci_r(n - 2)ret := simplemath.Add(lhs, rhs)return ret, nil
}
src/simplemath/add.go
package simplemathfunc Add(a int, b int) int {return a + b
}
src/simplemath/sqrt.go
package simplemathimport "math"func Sqrt(i int) int {v := math.Sqrt(float64(i))return int(v)
}
一键编译
首先,将工程路径添加到环境变量。
然后,用go install
命令一键编译
- gc
go install ./...
- gccgo
go install -compiler gccgo ./...
gc编译静态库
- 用
go tool compile
编译出二进制文件 - 用
go tool pack
打包成静态库
注意事项:
- 同一个包要编译成同一个
.o
文件 - gc静态库的命名规则是
gopackage.a
- 以后使用这个静态库需要用到-I和-L参数
[user@host goprj]$ go tool compile -o simplemath.o src/simplemath/add.go src/simplemath/sqrt.go
[user@host goprj]$ go tool pack c pkg/linux_amd64/simplemath.a simplemath.o
[user@host goprj]$
[user@host goprj]$ go tool compile -o fibonacci.o -I pkg/linux_amd64 src/calc/fibonacci/fibonacci.go
[user@host goprj]$ go tool pack c pkg/linux_amd64/calc/fibonacci.a fibonacci.o
[user@host goprj]$
[user@host goprj]$ go tool compile -o calc.o -I pkg/linux_amd64 src/calc/calc.go
[user@host goprj]$ go tool link -o bin/calc -L pkg/linux_amd64 calc.o
[user@host goprj]$
gccgo编译静态库
- 用
gccgo
编译出二进制文件 - 用
ar
打包成静态库
注意事项:
- 同一个包要编译成同一个
.o
文件 - gccgo静态库的命名规则是
libgopackage.a
[user@host goprj]$ gccgo -c -o simplemath.o src/simplemath/add.go src/simplemath/sqrt.go
[user@host goprj]$ ar rv pkg/gccgo_linux_amd64/libsimplemath.a simplemath.o
ar: creating pkg/gccgo_linux_amd64/libsimplemath.a
a - simplemath.o
[user@host goprj]$
[user@host goprj]$ gccgo -c -o fibonacci.o -I pkg/gccgo_linux_amd64 src/calc/fibonacci/fibonacci.go
[user@host goprj]$ ar rv pkg/gccgo_linux_amd64/calc/libfibonacci.a fibonacci.o
ar: creating pkg/gccgo_linux_amd64/calc/libfibonacci.a
a - fibonacci.o
[user@host goprj]$
[user@host goprj]$ gccgo -c -o calc.o -I pkg/gccgo_linux_amd64 src/calc/calc.go
[user@host goprj]$ gccgo -o bin/calc \
> -L pkg/gccgo_linux_amd64 \
> -L pkg/gccgo_linux_amd64/calc \
> calc.o \
> -lfibonacci -lsimplemath
[user@host goprj]$
gccgo编译动态库
gcc有着丰富的编译经验,还提供了编译go动态库的工具。
最简单的方法是用-shared
编译选项
[user@host goprj]$ gccgo -shared -fPIC \
> -o pkg/gccgo_linux_amd64/libsimplemath.so \
> src/simplemath/add.go \
> src/simplemath/sqrt.go
[user@host goprj]$ gccgo -shared -fPIC \
> -o pkg/gccgo_linux_amd64/calc/libfibonacci.so \
> -I pkg/gccgo_linux_amd64 \
> src/calc/fibonacci/fibonacci.go
[user@host goprj]$
总结
总的来说,go tool非常方便,而手动编译更加灵活。
【Go语言】动态库和静态库详解相关推荐
- Gzip的动态压缩和静态压缩详解
Gzip的压缩分为动态压缩和静态压缩.动态压缩简而言之就是nginx上的资源是以原始文件形式存在的,当返回给浏览器的时候再进行压缩,浏览器收到压缩文件再解压缩.静态压缩就是nginx上的资源不是原始文 ...
- Java动态数组和静态数组详解
前言必读 读者手册(必读)_云边的快乐猫的博客-CSDN博客 数组: 概念:数组就是存储数据长度固定的容器,保证多个数据的数据类型要一致,不能出现混合类型 1.什么数据类型就只能储存什么数据元素,比 ...
- c语言仿ce内存搜索工 源代码_C语言函数库:动态库和静态库优缺点比较
函数的重要性 我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期的代码维护.我们可以把他们制 ...
- C语言函数库:动态库和静态库优缺点比较
函数的重要性 我们在编写一个C语言程序的时候,经常会遇到好多重复或常用的部分,如果每次都重新编写固然是可以的,不过那样会大大降低工作效率,并且影响代码的可读性,更不利于后期的代码维护.我们可以把他们制 ...
- 技巧:Linux 动态库与静态库制作及使用详解
http://www.ibm.com/developerworks/cn/linux/l-cn-linklib/ 技巧:Linux 动态库与静态库制作及使用详解 标准库的三种连接方式及静态库制作与使用 ...
- 【转】C语言如何编译动态库与静态库?
因为是别的论坛,不能直接转载,自己在这里再粘贴一下-- 转载网址:https://www.2cto.com/kf/201711/699202.html 关于动态库与静态库的作用这里就不在详细赘述了,重 ...
- linux系统中 库分为静态库和,Linux系统中“动态库”和“静态库”那点事儿-【经典好文】...
今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在这之前,我们需要了解一下源代码到可执行程序之间到底发生了什么神奇而美妙的事情. 在linux操作系统中,普遍使用E ...
- Linux 动态库和静态库
From:http://blog.csdn.net/u010977122/article/details/52958330 From:http://blog.163.com/xychenbaihu@y ...
- Linux系统中动态库和静态库的区别
Linux系统中"动态库"和"静态库"那点事儿 今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在这之前,我们需要了解一下源 ...
- Linux系统中的“动态库”和“静态库”
Linux系统中的"动态库"和"静态库" 在Linux操作系统中,普遍使用ELF格式作为可执行程序或者程序生成过程中的中间格式.ELF(Executable a ...
最新文章
- ACR2010_新版RA分类标准发现更多需要治疗和纳入临床试验的早期关节炎患者
- 【归并排序】求逆序数算法
- 微信小程序的点击复制功能
- 查看某个端口的进程 lsof -i:端口号
- 樊昌信版通信原理期末复习第一章绪论
- mysql 主主互备实现
- 信息学奥赛一本通 1035:等差数列末项计算 | OpenJudge NOI 1.3 18
- WebSVN(2.3.1版本)中文注释以及中文路径乱码的解决方法【未完待续】
- 纯CSS实现兼容ie6以上的圆角头像
- 【python】socket编程常量错误问题-1 'AF_INET'
- Mac 使用brew 安装adb
- 微信公众号Java开发:自动回复文字及图片,第三方接口
- 【转载】PyCharm 或者其他 Idea 官网打不开解决办法:
- Pinyin4j之Pinyin4jUtils工具类
- CSS3实现流星动画
- 2022年总结关于网络安全工程师职业发展方向和职业前景
- mysqldb mysql config_python 安装MySQLdb mysql_config not fount原因
- Java历史、现状和各版本技术更迭总结
- 北斗组网大功告成!你的手机真的能连上北斗吗
- vscode 自定义代码主题颜色