当前位置:网站首页>【Go语言】动态库和静态库详解
【Go语言】动态库和静态库详解
2022-07-17 00:10:00 【tissar】
【Go语言】动态库和静态库详解
前言
首先,引用七牛云存储团队在《Go语言编程》的观点(第7章,第9节):
就目前而言,以二进制方式分发Go包并不是很现实。由于Go语言对于兼容性控制的非常严格,任何一个版本号的不同都将导致无法链接包。因此,如果你使用Go语言开发了一个库,那么最合适的库分发方式是直接打包源代码包并进行分发,由使用者自行编译。
但是,笔者认为Go语言的编译和C语言一样,有汇编、链接阶段。所以,有必要了解、学习Go语言的动态库和静态库,也有助于以后分发包。
示例工程
一个标准的Golang工程包含3个目录
- bin 放可执行文件
- pkg 放静态库
- src 放源代码
[[email protected] goprj]$ ls
bin pkg src
[[email protected] goprj]$ tree
.
├── bin
├── pkg
│ ├── gccgo_linux_amd64
│ └── linux_amd64
└── src
├── calc
│ ├── fibonacci
│ │ ├── fibonacci.go
│ │ └── fibonacci_test.go
│ └── calc.go
└── simplemath
├── add.go
└── sqrt.go
6 directories, 5 files
[[email protected] 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 main
import "fmt"
import "calc/fibonacci"
func main() {
var res int64
var err error
res, 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 fibonacci
import "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 = 0
var tmp int64 = 1
var idx int64 = 0
for ; 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 simplemath
func Add(a int, b int) int {
return a + b
}
src/simplemath/sqrt.go
package simplemath
import "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参数
[[email protected] goprj]$ go tool compile -o simplemath.o src/simplemath/add.go src/simplemath/sqrt.go
[[email protected] goprj]$ go tool pack c pkg/linux_amd64/simplemath.a simplemath.o
[[email protected] goprj]$
[[email protected] goprj]$ go tool compile -o fibonacci.o -I pkg/linux_amd64 src/calc/fibonacci/fibonacci.go
[[email protected] goprj]$ go tool pack c pkg/linux_amd64/calc/fibonacci.a fibonacci.o
[[email protected] goprj]$
[[email protected] goprj]$ go tool compile -o calc.o -I pkg/linux_amd64 src/calc/calc.go
[[email protected] goprj]$ go tool link -o bin/calc -L pkg/linux_amd64 calc.o
[[email protected] goprj]$
gccgo编译静态库
- 用
gccgo编译出二进制文件 - 用
ar打包成静态库
注意事项:
- 同一个包要编译成同一个
.o文件 - gccgo静态库的命名规则是
libgopackage.a
[[email protected] goprj]$ gccgo -c -o simplemath.o src/simplemath/add.go src/simplemath/sqrt.go
[[email protected] goprj]$ ar rv pkg/gccgo_linux_amd64/libsimplemath.a simplemath.o
ar: creating pkg/gccgo_linux_amd64/libsimplemath.a
a - simplemath.o
[[email protected] goprj]$
[[email protected] goprj]$ gccgo -c -o fibonacci.o -I pkg/gccgo_linux_amd64 src/calc/fibonacci/fibonacci.go
[[email protected] goprj]$ ar rv pkg/gccgo_linux_amd64/calc/libfibonacci.a fibonacci.o
ar: creating pkg/gccgo_linux_amd64/calc/libfibonacci.a
a - fibonacci.o
[[email protected] goprj]$
[[email protected] goprj]$ gccgo -c -o calc.o -I pkg/gccgo_linux_amd64 src/calc/calc.go
[[email protected] goprj]$ gccgo -o bin/calc \
> -L pkg/gccgo_linux_amd64 \
> -L pkg/gccgo_linux_amd64/calc \
> calc.o \
> -lfibonacci -lsimplemath
[[email protected] goprj]$
gccgo编译动态库
gcc有着丰富的编译经验,还提供了编译go动态库的工具。
最简单的方法是用-shared编译选项
[[email protected] goprj]$ gccgo -shared -fPIC \
> -o pkg/gccgo_linux_amd64/libsimplemath.so \
> src/simplemath/add.go \
> src/simplemath/sqrt.go
[[email protected] goprj]$ gccgo -shared -fPIC \
> -o pkg/gccgo_linux_amd64/calc/libfibonacci.so \
> -I pkg/gccgo_linux_amd64 \
> src/calc/fibonacci/fibonacci.go
[[email protected] goprj]$
总结
总的来说,go tool非常方便,而手动编译更加灵活。
边栏推荐
猜你喜欢

Scala environment construction

Scala环境搭建

普通异步发送代码编写

VSCode中安装Go:tools failed to install.

Introduction to software vulnerability analysis (4)

Common asynchronous sending code writing

How to use express and how to match and use routes

TCP and UDP, TCP server and client, UDP server and client

touchID 和 FaceID~2

Why do you spend 1.16 million to buy an NFT avatar in the library of NFT digital collections? The answer may be found by reviewing the "rise history" of NFT avatars
随机推荐
fetch请求-简单记录
基于CSI的通信感知一体化设计:问题、挑战和展望
mysql innodb 事务相关记录
4章 性能平台GodEye源码分析-监控模块
Cocos Creator 3.0 基础——事件系统
普通异步发送代码编写
通感一体化融合的研究及其挑战
8 找到和最大的长度为 K 的子序列
同学们 小组作业记得别抄哈 幸好只传了两道题 不要出事了
基于开源流批一体数据同步引擎ChunJun数据还原—DDL解析模块的实战分享
touchID 和 FaceID~1
一文盘点估值超过1亿美元的NFT项目
感通融合系统中保障公平度的时间与功率分配方法
为什么说 OpenSea 是 NFT 交易市场的绝对垄断者?
IPFs mount to local disk
通信感知一体化应用场景、关键技术和网络架构
Swift 【Class】【struct】
nft发行价格是多少(解读NFT建立起NFT世界观)
WKWebView 设置自定义UserAgent正确姿势
【文献阅读】MCUNet: Tiny Deep Learning on IoT Devices