Golang在嵌入式开发的调研
支持的ARM架构[1]
架构 | 状态 | GOARM值 | GOARCH值 |
---|---|---|---|
ARMv4 及以下 | 不支持 | 无 | 无 |
ARMv5 | 支持 | GOARM=5 | GOARCH=arm |
ARMv6 | 支持 | GOARM=6 | GOARCH=arm |
ARMv7 | 支持 | GOARM=7 | GOARCH=arm |
ARMv8 | 支持 | 无 | GOARCH=arm64 |
可以使用 go tool dist list
命令来查看Go支持的目标平台和架构,也可以使用 go tool dist list -json
命令查看更详细的信息。
操作系统要求[1]
- ARM on Linux:操作系统必须使用 EABI 内核。对于armel设备与ARMv5兼容,armhf设备与ARMv6及更高处理器架构兼容。
- ARM on FreeBSD, OpenBSD, and NetBSD:需要ARMv6K处理器架构或更高
提示与技巧[1]
- golang在编译与测试时大量使用
/tmp
目录,如果你的/tmp
目录挂在SD卡上,会对SD造成大量损耗,可以使用export TMPDIR
使golang构建工具使用其他目录。 - 从源码编译构建golang需要至少256mb内存。
- 因为golang在运行测试时会大量创建线程,所以如果测试时因为资源不足测试失败的话,可以减少最大线程栈大小。比如使用
ulimit -s 1024
将其设置为1mb。
编译[2]
Go默认使用静态编译,所以编译出来的二进制文件很大。我们可以稍作处理在一定程度上减小程序大小。最简单的就是设置编译选项来减少某些内容来减少程序大小:
bash
go build -ldflags="-s -w"
# -s:忽略符号表和调试信息
# -w:忽略DWARFv3调试信息,使用该选项后将无法使用gdb进行调试
# 也可以使用strip消除Go的编译信息
也可以使用UPX工具,其原理是将打包出来的二进制文件进行压缩,然后在头部加入解压缩指令,所以体积上可以减小非常多,不过换来的代价是程序启动的时候解压会有少许时间消耗。另外upx也有其可适用的目标平台,详细内容可以参考其自带的文档。
Go也可以动态编译,不过那样用起来就麻烦了。查了一下,动态编译内容很少,而且用起来就比较麻烦了。
交叉编译[3]
GO OS / GO ARCH | amd64 | 386 | arm | arm64 | ppc64le | ppc64 | mips64le | mips64 | mipsle | mips | wasm | risc64 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
aix | ✓ | |||||||||||
android | ✓ | ✓ | ✓ | ✓ | ||||||||
darwin | ✓ | ✓ | ||||||||||
dragonfly | ✓ | |||||||||||
freebsd | ✓ | ✓ | ✓ | |||||||||
illumos | ✓ | |||||||||||
ios | ✓ | |||||||||||
js | ✓ | |||||||||||
linux | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | |
netbsd | ✓ | ✓ | ✓ | |||||||||
openbsd | ✓ | ✓ | ✓ | ✓ | ||||||||
plan9 | ✓ | ✓ | ✓ | |||||||||
solaris | ✓ | |||||||||||
windows | ✓ | ✓ | ✓ | ✓ |
Go和C语言的比较[3]
要求 | C | C++ | Go |
---|---|---|---|
设备存储要求 | 最低 | 低(多出1.8MB) | 低(多出2.1MB) |
Yocto中的安装要求 | 无 | 无 | 无 |
缓冲器不足/溢出保护 | 无 | 轻度 | 是 |
CFEngine代码重用/共享 | 好 | 简单(完全向后兼容) | 可以导入C接口 |
自动内存管理 | 否 | 可用,但非强制启用 | 是 |
标准数据容器 | 否 | 是 | 是 |
JSON | json-C | jsoncpp | 内置 |
HTTP库 | curl | curl | 内置 |
SSL/TLS | OpenSSL | OpenSSL | 内置 |
评估团队使用Yocto创建一个完善的定制Linux映像,比较了原始的映像体积较之具有网络堆栈的映像体积,以及最终应用程序写入映像的方式。
C | C++ | C++/Qt | Go | |
---|---|---|---|---|
以最小可用Yocto映像为基础测试所有组件和库的大小 | 8.4MB | 10.2MB | 20.8MB | 14.6MB |
网络堆栈大小 | 13.4MB(curl) | 15.2MB(curl) | 20.8MB | 14.6MB |
共享依赖关系 | 是 | 是 | 是 | 否 |
需要额外的Yocto层 | 否 | 否 | 是 | 否 |
部署复杂性 | 二进制 | 二进制 | 二进制+Qt | 二进制 |
使用最基本的“hello world” 代码进行体积比较:
Golang:
go
package main
import "fmt"
func main() {
fmt.Println("hello,world!")
}
$ go build
> 1.9MB
$ go build -ldflags ‘-s -w’
> 1.3MB
C:
C
#include <stdio.h>
int main() {
printf("Hello, World!
");
return 0;
}
$ gcc main.c -o main
> 49KB
C++:
c++
#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
$ g++ main.c -o main
> 56KB