
Golang
Go模块代理大全
编程 push 发表了文章 0 个评论 5206 次浏览 2021-04-22 17:34

1.GoProxy
官网地址: https://www.goproxy.io/zh/
Bash (Linux or macOS):
# 配置 GOPROXY 环境变量
export GOPROXY=https://goproxy.io,direct
# 还可以设置不走 proxy 的私有仓库或组,多个用逗号相隔(可选)
export GOPRIVATE=git.mycompany.com,github.com/my/private
PowerShell (Windows)
# 配置 GOPROXY 环境变量
$env:GOPROXY = "https://goproxy.io,direct"
# 还可以设置不走 proxy 的私有仓库或组,多个用逗号相隔(可选)
$env:GOPRIVATE = "git.mycompany.com,github.com/my/private"
设置完上面几个环境变量后,您的 go 命令将从公共代理镜像中快速拉取您所需的依赖代码了。或者,还可以根据文档进行设置使其长期生效。如果您使用的是老版本的 Go(< 1.13), 我们建议您升级为最新稳定版本。
2.七牛GoProxy中国
官网地址:https://goproxy.cn/
Go 1.13 及以上(推荐),打开你的终端并执行
$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct
macOS 或 Linux
$ export GO111MODULE=on
$ export GOPROXY=https://goproxy.cn
或者
$ echo "export GO111MODULE=on" >> ~/.profile
$ echo "export GOPROXY=https://goproxy.cn" >> ~/.profile
$ source ~/.profile
Windows, 打开你的 PowerShell 并执行
C:\> $env:GO111MODULE = "on"
C:\> $env:GOPROXY = "https://goproxy.cn"
或者
1. 打开“开始”并搜索“env”
2. 选择“编辑系统环境变量”
3. 点击“环境变量…”按钮
4. 在“<你的用户名> 的用户变量”章节下(上半部分)
5. 点击“新建…”按钮
6. 选择“变量名”输入框并输入“GO111MODULE”
7. 选择“变量值”输入框并输入“on”
8. 点击“确定”按钮
9. 点击“新建…”按钮
10. 选择“变量名”输入框并输入“GOPROXY”
11. 选择“变量值”输入框并输入“https://goproxy.cn”
12. 点击“确定”按钮
3.百度Go Module代理
官网地址: https://goproxy.baidu.com/
简介:go module公共代理仓库,代理并缓存go模块。你可以利用该代理来避免DNS污染导致的模块拉取缓慢或失败的问题,加速你的构建
1.使用go1.11以上版本并开启go module机制
export GOPROXY=https://goproxy.baidu.com/ ## 配置GOPROXY环境变量
2.使用go1.13以上版本
go env -w GONOPROXY=\*\*.baidu.com\*\* ## 配置GONOPROXY环境变量,所有百度内代码,不走代理
go env -w GONOSUMDB=\* ## 配置GONOSUMDB,暂不支持sumdb索引
go env -w GOPROXY=https://goproxy.baidu.com ## 配置GOPROXY,可以下载墙外代码
4.阿里云Go Module代理
官网:http://mirrors.aliyun.com/goproxy/
1.使用go1.11以上版本并开启go module机制
2.导出GOPROXY环境变量
export GOPROXY=https://mirrors.aliyun.com/goproxy/
官网安装包国内下载地址
- Go中文社区:https://studygolang.com/dl
- Gomirrors: https://gomirrors.org/
Go交叉编译的那些事
编程 星物种 发表了文章 0 个评论 5062 次浏览 2021-03-25 23:00

最近两个月,一直在搞项目的国产化移植,把golang开发好的程序,运行在国产化平台上,操作系统基本都是基于Linux,但是CPU架构除了x86,还有ARM和MIPS,我们平时的Golang都是运行于x86 && x64 架构的CPU上,因此移植过程中遇到了好多坑,记录于此。
Golang交叉编译
交叉编译
在X64上的ubuntu 16.04
系统上编译出其他平台的可执行程序, 查看Golang支持的平台和版本:
go tool dist list
此命令会列出所有go语言支持的操作系统和cpu架构
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/amd64
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
illumos/amd64
js/wasm
linux/386
linux/amd64
linux/arm
linux/arm64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/riscv64
linux/s390x
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
plan9/386
plan9/amd64
plan9/arm
solaris/amd64
windows/386
windows/amd64
windows/arm
其实go的交叉编译非常简单,只需要在编译前指定系统和CPU架构,基本不会有任何问题,编译出来将文件拷贝到对应平台就能跑:
GOOS=linux GOARCH=arm64 go build xxx.go
# 有时候需要加上CGO_ENABLE=0
CGO_ENABLE=0 GOOS=linux GOARCH=arm64 go build xxx.go
go语言的交叉编译支持非常好,只要按照上述步骤基本不会出什么问题。坑,主要就坑在cgo, CGO_ENABLED=0 关闭cgo。
采用cgo的交叉编译
使用cgo,就必须指定CGO_ENABLE=1。并且必须指定CC参数为对应架构的gcc的交叉编译器。
假设我们编译64位ARM平台的程序,就要提前下载aarch64版本的c++交叉编译工具
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=./aarch64-unknown-linux-gnueabi-5.4.0-2.23-4.4.6/bin/aarch64-unknown-linux-gnueabi-gcc go build xxx.go
如果调用的CGO调用的C程序中依赖各种库,那么这个编译过程会报错各种依赖的库not found
,各种基本的函数
未定义。而且都是系统中最基本的库如libglibc、libgstream
等。
解决方案是必须在编译时,加上链接库的参数,而链接的库必须是
交叉编译出的目标平台
的系统库而不是当前
系统的。
这个在下载交叉编译工具链的时候,一般都会附带,我这里放到系统根目录下,然后通过C++编译时链接库的语法将库链接进去:
主要是三个参数:-I , -isystem , -L, -l
下面命令是个例子,假设项目中用到了phnono、curl、protobuf
等组件:
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=./aarch64-unknown-linux-gnueabi-5.4.0-2.23-4.4.6/bin/aarch64-unknown-linux-gnueabi-gcc -Wall -std=c++11 -Llib -isystem/aarch64/usr/include -L/aarch64/lib -ldl -lpthread -Wl,-rpath-link,/aarch64/lib -L/aarch64/lib/aarch64-linux-gnu -L/aarch64/usr/lib -I/aarch64/usr/include -L/aarch64/usr/lib/aarch64-linux-gnu -ldl -lpthread -Wl,-rpath-link,/aarch64/usr/lib/aarch64-linux-gnu -lphonon -lcurl -lprotobuf go build xxx.go
到这一步,就基本解决了无法编译的坑。
平台差异的问题
在编译ARM版本的代码时,报错好几个系统调用找不到:
- undefined: syscall.Dup2
- undefined: syscall.SYS_FORK
解决方案:对比golang源码实现:go/src/syscall/zsyscall_linux_amd64.go
和go/src/syscall/zsyscall_linux_arm64.go
,发现arm平台未实现Dup2
但是提供了Dup3,参数略有差异,解决办法是修改调用的地方:
// - syscall.Dup2(oldfd, newfd) 修改为:
syscall.Dup3(oldfd,newfd,0)
而SYS_FORK
的调用,查找之下发现golang
的ARM实现根本没有实现fork的系统调用,没有SYS_FORK
这个宏或替代品。
无奈只能修改项目代码,将fork的系统调用改为别的方式实现。
MIPS的大小端问题
报错:go.o: compiled for a big endian system and target is little endian
主要体现在大小端字节序的问题,这是我在交叉编译Mips版本发现的一个问题,仔细查看了我的编译命令发现:
CGO_ENABLED=1 GOOS=linux GOARCH=mips64 CC=./mips64el-unknown-linux-gnu-5.4.0-2.12-2.6.32/bin/mips64el-unknown-linux-gnu-gcc go build xxx.go
这里的命令中:CC指定的是mips64el的编译器,el代表小端字节序,而GOARCH=mips64
这是大端字节序,前后不一致导致编译的报错,
解决方案:go和gcc保持统一、以目标平台为准(龙芯是小端字节序)
- 将GOARCH指定为mips64le(注意是le不是el)
- 最好加上LDFLAG=-EL
CGO_ENABLED=1 GOOS=linux GOARCH=mips64le CC=./mips64el-unknown-linux-gnu-5.4.0-2.12-2.6.32/bin/mips64el-unknown-linux-gnu-gcc LDFLAGS=-EL go build xxx.go
总结经验:
1. golang程序开发少用原生的系统调用syscall
2. 能用go解决的,尽可能不要用cgo
3. 如果有模块必须通过C/C++调用,推荐C++和golang分离,C++和Golang程序间使用socket等方式进行进程间通信
分享阅读原文:https://henduan.com/wNyCI
golang静态编译
编程 Ansible 发表了文章 0 个评论 2218 次浏览 2020-04-30 09:43

golang 的编译(不涉及 cgo 编译的前提下)默认使用了静态编译,不依赖任何动态链接库。
这样可以任意部署到各种运行环境,不用担心依赖库的版本问题。只是体积大一点而已,存储时占用了一点磁盘,运行时,多占用了一点内存。早期动态链接库的产生,是因为早期的系统的内存资源十分宝贵,由于内存紧张的问题在早期的系统中显得更加突出,因此人们首先想到的是要解决内存使用效率不高这一问题,于是便提出了动态装入的思想。也就产生了动态链接库。在现在的计算机里,操作系统的硬盘内存更大了,尤其是服务器,32G、64G 的内存都是最基本的。可以不用为了节省几百 KB 或者1M,几 M 的内存而大大费周折了。而 golang 就采用这种做法,可以避免各种 so 动态链接库依赖的问题,这点是非常值得称赞的。
显示指定静态编译方法
在Docker化的今天, 我们经常需要静态编译一个Go程序,以便方便放在Docker容器中。 即使你没有引用其它的第三方包,只是在程序中使用了标准库net,你也会发现你编译后的程序依赖glic,这时候你需要glibc-static库,并且静态连接。
不同的Go版本下静态编译方式还有点不同,在go 1.10下, 下面的方式会尽可能做到静态编译:
CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' .
Go Web框架gin vs echo
编程 koyo 发表了文章 0 个评论 7758 次浏览 2017-09-10 20:36
Web框架类型
web框架的主流,是采用轻量级的中间件式框架,把网站变成只有api的一个个小服务,其他都扔到cdn之类的地方处理。
这种方式,开发快速、拼装能力强,要什么就加什么,不要的就不加,就像是乐高玩具,大受欢迎。
问题在于,这种框架有一堆,到底该选哪个。
Gin vs Echo
在golang中,这种杰出代表,有2个:gin 和 echo。
这两个框架,在同类中,路由性能最高,超出其他框架一大截。google了一大堆英文站,也没有找到这两个框架的比较。于是,在我们实际使用后,提供个比较。
先说结论:
- 如果你代表企业,最好选择gin,无痛开发。
- 如果是个人,开发个轻量服务,哪怕echo有点小问题,你也觉得没啥,那么,就用echo。
gin完胜框架成熟度
- gin拥有详尽的出错信息,极为方便调试。
- 这非常关键。团队项目,这个更加重要。
- echo在这方面,就略微逊色。使用框架的第一天,就遇到了明明路由语法写错了,却不报错、不给结果,也没有任何提示的情况。
gin微弱小胜路由性能
- gin的卖点,是所有web框架中,路由性能最好。
- echo的卖点,是它的路由性能,比gin还好10%。
一回事,都有点小不便:路由便利、灵活性
- 两个路由采用同一种算法,这种算法性能很高,但有个缺点: 不支持路由排序,会认为是路由冲突。
- 比如: 路由Get("/name")和 Get("/:id") ,一般来说,只要把Get("/name")放在Get("/:id")前面,就是不冲突的。路由模块,会先尝试匹配前面那个,没匹配上,再去匹配后面的。
- 而 gin和echo用的路由模块,会认为这两个路由是冲突的。gin会给出提醒,不让编译通过;echo完全不提醒,冲突就冲突了。。。
两个都不够好。框架的可持续发展
- gin的主创是2个大学生。每年寒暑假就频繁更新,快到期末考试了,就完全不更新了。两人不在的时候,有网友在帮忙热情的维护,但主要是修bug、整理中间件。框架本身的发展,还是靠主创寒暑假爆发。就是这样的框架,连csico都在用。。。
- 好在,gin的代码注释量大,易读性高,便于其他人参与。而且包装中间件,也超级容易。
- 作者本人的态度是,对于一个在github上,start达到5000+的项目,他怎么可能会不去维护。请大家放心使用,到寒暑假了,他自然会去更新。。。
- echo则是主创当前处于活跃状态,并且乐呵呵的想要开发2.0版。由于主创活跃,它自带了一些流行功能,比如websocket, http2, jwt授权。用gin的话,这些功能要自己包装个中间件,虽然也很容易就是了。
- 但echo的问题在于,它的代码毫无注释。作者现在是在劲头上,等3-6个月,在路上看到个穿超短的妹子,热情转移了,很快就会忘记当时代码是怎么写的。没有注释,不但别人不方便接手,自己也懒得再去看,于是慢慢就永不再更新。
- 缺少注释的开源包,大部分都有这个问题。echo最终会不会变成这个结局,我们无从得知。
综上总结
- echo的状态是当下主创本人活跃,框架还不太成熟,适合最轻量级服务;
- gin则是整体成熟、易于调试,但可以预期,框架本身发展不会太快,除非主创大学毕业,从事和golang相关的工作。
- echo的使用方式、命名,都参考了gin,两者很接近,切换框架很容易,所以不用担心选错。
更新
由于echo的路由冲突频繁且没有调试信息,目前不是合理选择。等作者补上了路由冲突检测,那么就还不错。
如果想要回避这种框架的路由冲突,又想享受类似的优秀,neo框架目前最接近.
原文地址:https://www.golangtc.com/t/56a38761b09ecc083100010c
Golang两种MD5加密方式
编程 Rock 发表了文章 0 个评论 6515 次浏览 2015-12-01 19:53
代码
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
)
func main() {
// md5 加密的第一种方法
srcData := []byte("iyannik0215")
cipherText1 := md5.Sum(srcData)
fmt.Printf("md5 encrypto is \"iyannik0215\": %x \n", cipherText1)
// md5 加密的第二种方法
hash := md5.New()
hash.Write(srcData)
cipherText2 := hash.Sum(nil)
hexText := make([]byte, 32)
hex.Encode(hexText, cipherText2)
fmt.Println("md5 encrypto is \"iyannik0215\":", string(hexText))
}
# 执行结果
md5 encrypto is "iyannik0215": b6b20c73e6bc53bc691a6bb559cf9ca9
md5 encrypto is "iyannik0215": b6b20c73e6bc53bc691a6bb559cf9ca9
不同
解释一下两种加密方式的不一样之处.
第一种加密方法:
第一种加密方法所调用的函数
//Source file src/crypto/md5/md5.gofunc Sum(data []byte) [Size]byte
19 // The size of an MD5 checksum in bytes.
20 const Size = 16
130 // Sum returns the MD5 checksum of the data.
131 func Sum(data []byte) [Size]byte {
132 var d digest
133 d.Reset()
134 d.Write(data)
135 return d.checkSum()
136 }
其 [Size]byte 是固定死的.所以说第一种方法返回的是 16长度的数组.
第二种加密方法:
//Source file src/crypto/md5/md5.go这里使用 func New() hash.Hash {} 函数进行生成对象.
50 // New returns a new hash.Hash computing the MD5 checksum.
51 func New() hash.Hash {
52 d := new(digest)
53 d.Reset()
54 return d
55 }
// 这里只放了函数签名部分, 关于函数具体内容这里就不详细复制了.
51 func New() hash.Hash {}
61 func (d *digest) Write(p []byte) (nn int, err error) {}
90 func (d0 *digest) Sum(in []byte) []byte {}
使用 func (d *digest) Write(p []byte) (nn int, err error) {} 方法进行写入要加密的数据.
使用 func (d0 *digest) Sum(in []byte) []byte {} 方法进行数据的加密 看其返回值.
[]byte 可见使用第二种方式加密返回的是 []byte 类型的切片.
Go模块代理大全
编程 push 发表了文章 0 个评论 5206 次浏览 2021-04-22 17:34

1.GoProxy
官网地址: https://www.goproxy.io/zh/
Bash (Linux or macOS):
# 配置 GOPROXY 环境变量
export GOPROXY=https://goproxy.io,direct
# 还可以设置不走 proxy 的私有仓库或组,多个用逗号相隔(可选)
export GOPRIVATE=git.mycompany.com,github.com/my/private
PowerShell (Windows)
# 配置 GOPROXY 环境变量
$env:GOPROXY = "https://goproxy.io,direct"
# 还可以设置不走 proxy 的私有仓库或组,多个用逗号相隔(可选)
$env:GOPRIVATE = "git.mycompany.com,github.com/my/private"
设置完上面几个环境变量后,您的 go 命令将从公共代理镜像中快速拉取您所需的依赖代码了。或者,还可以根据文档进行设置使其长期生效。如果您使用的是老版本的 Go(< 1.13), 我们建议您升级为最新稳定版本。
2.七牛GoProxy中国
官网地址:https://goproxy.cn/
Go 1.13 及以上(推荐),打开你的终端并执行
$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct
macOS 或 Linux
$ export GO111MODULE=on
$ export GOPROXY=https://goproxy.cn
或者
$ echo "export GO111MODULE=on" >> ~/.profile
$ echo "export GOPROXY=https://goproxy.cn" >> ~/.profile
$ source ~/.profile
Windows, 打开你的 PowerShell 并执行
C:\> $env:GO111MODULE = "on"
C:\> $env:GOPROXY = "https://goproxy.cn"
或者
1. 打开“开始”并搜索“env”
2. 选择“编辑系统环境变量”
3. 点击“环境变量…”按钮
4. 在“<你的用户名> 的用户变量”章节下(上半部分)
5. 点击“新建…”按钮
6. 选择“变量名”输入框并输入“GO111MODULE”
7. 选择“变量值”输入框并输入“on”
8. 点击“确定”按钮
9. 点击“新建…”按钮
10. 选择“变量名”输入框并输入“GOPROXY”
11. 选择“变量值”输入框并输入“https://goproxy.cn”
12. 点击“确定”按钮
3.百度Go Module代理
官网地址: https://goproxy.baidu.com/
简介:go module公共代理仓库,代理并缓存go模块。你可以利用该代理来避免DNS污染导致的模块拉取缓慢或失败的问题,加速你的构建
1.使用go1.11以上版本并开启go module机制
export GOPROXY=https://goproxy.baidu.com/ ## 配置GOPROXY环境变量
2.使用go1.13以上版本
go env -w GONOPROXY=\*\*.baidu.com\*\* ## 配置GONOPROXY环境变量,所有百度内代码,不走代理
go env -w GONOSUMDB=\* ## 配置GONOSUMDB,暂不支持sumdb索引
go env -w GOPROXY=https://goproxy.baidu.com ## 配置GOPROXY,可以下载墙外代码
4.阿里云Go Module代理
官网:http://mirrors.aliyun.com/goproxy/
1.使用go1.11以上版本并开启go module机制
2.导出GOPROXY环境变量
export GOPROXY=https://mirrors.aliyun.com/goproxy/
官网安装包国内下载地址
- Go中文社区:https://studygolang.com/dl
- Gomirrors: https://gomirrors.org/
Go交叉编译的那些事
编程 星物种 发表了文章 0 个评论 5062 次浏览 2021-03-25 23:00

最近两个月,一直在搞项目的国产化移植,把golang开发好的程序,运行在国产化平台上,操作系统基本都是基于Linux,但是CPU架构除了x86,还有ARM和MIPS,我们平时的Golang都是运行于x86 && x64 架构的CPU上,因此移植过程中遇到了好多坑,记录于此。
Golang交叉编译
交叉编译
在X64上的ubuntu 16.04
系统上编译出其他平台的可执行程序, 查看Golang支持的平台和版本:
go tool dist list
此命令会列出所有go语言支持的操作系统和cpu架构
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/amd64
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
illumos/amd64
js/wasm
linux/386
linux/amd64
linux/arm
linux/arm64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/riscv64
linux/s390x
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
plan9/386
plan9/amd64
plan9/arm
solaris/amd64
windows/386
windows/amd64
windows/arm
其实go的交叉编译非常简单,只需要在编译前指定系统和CPU架构,基本不会有任何问题,编译出来将文件拷贝到对应平台就能跑:
GOOS=linux GOARCH=arm64 go build xxx.go
# 有时候需要加上CGO_ENABLE=0
CGO_ENABLE=0 GOOS=linux GOARCH=arm64 go build xxx.go
go语言的交叉编译支持非常好,只要按照上述步骤基本不会出什么问题。坑,主要就坑在cgo, CGO_ENABLED=0 关闭cgo。
采用cgo的交叉编译
使用cgo,就必须指定CGO_ENABLE=1。并且必须指定CC参数为对应架构的gcc的交叉编译器。
假设我们编译64位ARM平台的程序,就要提前下载aarch64版本的c++交叉编译工具
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=./aarch64-unknown-linux-gnueabi-5.4.0-2.23-4.4.6/bin/aarch64-unknown-linux-gnueabi-gcc go build xxx.go
如果调用的CGO调用的C程序中依赖各种库,那么这个编译过程会报错各种依赖的库not found
,各种基本的函数
未定义。而且都是系统中最基本的库如libglibc、libgstream
等。
解决方案是必须在编译时,加上链接库的参数,而链接的库必须是
交叉编译出的目标平台
的系统库而不是当前
系统的。
这个在下载交叉编译工具链的时候,一般都会附带,我这里放到系统根目录下,然后通过C++编译时链接库的语法将库链接进去:
主要是三个参数:-I , -isystem , -L, -l
下面命令是个例子,假设项目中用到了phnono、curl、protobuf
等组件:
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=./aarch64-unknown-linux-gnueabi-5.4.0-2.23-4.4.6/bin/aarch64-unknown-linux-gnueabi-gcc -Wall -std=c++11 -Llib -isystem/aarch64/usr/include -L/aarch64/lib -ldl -lpthread -Wl,-rpath-link,/aarch64/lib -L/aarch64/lib/aarch64-linux-gnu -L/aarch64/usr/lib -I/aarch64/usr/include -L/aarch64/usr/lib/aarch64-linux-gnu -ldl -lpthread -Wl,-rpath-link,/aarch64/usr/lib/aarch64-linux-gnu -lphonon -lcurl -lprotobuf go build xxx.go
到这一步,就基本解决了无法编译的坑。
平台差异的问题
在编译ARM版本的代码时,报错好几个系统调用找不到:
- undefined: syscall.Dup2
- undefined: syscall.SYS_FORK
解决方案:对比golang源码实现:go/src/syscall/zsyscall_linux_amd64.go
和go/src/syscall/zsyscall_linux_arm64.go
,发现arm平台未实现Dup2
但是提供了Dup3,参数略有差异,解决办法是修改调用的地方:
// - syscall.Dup2(oldfd, newfd) 修改为:
syscall.Dup3(oldfd,newfd,0)
而SYS_FORK
的调用,查找之下发现golang
的ARM实现根本没有实现fork的系统调用,没有SYS_FORK
这个宏或替代品。
无奈只能修改项目代码,将fork的系统调用改为别的方式实现。
MIPS的大小端问题
报错:go.o: compiled for a big endian system and target is little endian
主要体现在大小端字节序的问题,这是我在交叉编译Mips版本发现的一个问题,仔细查看了我的编译命令发现:
CGO_ENABLED=1 GOOS=linux GOARCH=mips64 CC=./mips64el-unknown-linux-gnu-5.4.0-2.12-2.6.32/bin/mips64el-unknown-linux-gnu-gcc go build xxx.go
这里的命令中:CC指定的是mips64el的编译器,el代表小端字节序,而GOARCH=mips64
这是大端字节序,前后不一致导致编译的报错,
解决方案:go和gcc保持统一、以目标平台为准(龙芯是小端字节序)
- 将GOARCH指定为mips64le(注意是le不是el)
- 最好加上LDFLAG=-EL
CGO_ENABLED=1 GOOS=linux GOARCH=mips64le CC=./mips64el-unknown-linux-gnu-5.4.0-2.12-2.6.32/bin/mips64el-unknown-linux-gnu-gcc LDFLAGS=-EL go build xxx.go
总结经验:
1. golang程序开发少用原生的系统调用syscall
2. 能用go解决的,尽可能不要用cgo
3. 如果有模块必须通过C/C++调用,推荐C++和golang分离,C++和Golang程序间使用socket等方式进行进程间通信
分享阅读原文:https://henduan.com/wNyCI
golang静态编译
编程 Ansible 发表了文章 0 个评论 2218 次浏览 2020-04-30 09:43

golang 的编译(不涉及 cgo 编译的前提下)默认使用了静态编译,不依赖任何动态链接库。
这样可以任意部署到各种运行环境,不用担心依赖库的版本问题。只是体积大一点而已,存储时占用了一点磁盘,运行时,多占用了一点内存。早期动态链接库的产生,是因为早期的系统的内存资源十分宝贵,由于内存紧张的问题在早期的系统中显得更加突出,因此人们首先想到的是要解决内存使用效率不高这一问题,于是便提出了动态装入的思想。也就产生了动态链接库。在现在的计算机里,操作系统的硬盘内存更大了,尤其是服务器,32G、64G 的内存都是最基本的。可以不用为了节省几百 KB 或者1M,几 M 的内存而大大费周折了。而 golang 就采用这种做法,可以避免各种 so 动态链接库依赖的问题,这点是非常值得称赞的。
显示指定静态编译方法
在Docker化的今天, 我们经常需要静态编译一个Go程序,以便方便放在Docker容器中。 即使你没有引用其它的第三方包,只是在程序中使用了标准库net,你也会发现你编译后的程序依赖glic,这时候你需要glibc-static库,并且静态连接。
不同的Go版本下静态编译方式还有点不同,在go 1.10下, 下面的方式会尽可能做到静态编译:
CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' .
Go Web框架gin vs echo
编程 koyo 发表了文章 0 个评论 7758 次浏览 2017-09-10 20:36
Web框架类型
web框架的主流,是采用轻量级的中间件式框架,把网站变成只有api的一个个小服务,其他都扔到cdn之类的地方处理。
这种方式,开发快速、拼装能力强,要什么就加什么,不要的就不加,就像是乐高玩具,大受欢迎。
问题在于,这种框架有一堆,到底该选哪个。
Gin vs Echo
在golang中,这种杰出代表,有2个:gin 和 echo。
这两个框架,在同类中,路由性能最高,超出其他框架一大截。google了一大堆英文站,也没有找到这两个框架的比较。于是,在我们实际使用后,提供个比较。
先说结论:
- 如果你代表企业,最好选择gin,无痛开发。
- 如果是个人,开发个轻量服务,哪怕echo有点小问题,你也觉得没啥,那么,就用echo。
gin完胜框架成熟度
- gin拥有详尽的出错信息,极为方便调试。
- 这非常关键。团队项目,这个更加重要。
- echo在这方面,就略微逊色。使用框架的第一天,就遇到了明明路由语法写错了,却不报错、不给结果,也没有任何提示的情况。
gin微弱小胜路由性能
- gin的卖点,是所有web框架中,路由性能最好。
- echo的卖点,是它的路由性能,比gin还好10%。
一回事,都有点小不便:路由便利、灵活性
- 两个路由采用同一种算法,这种算法性能很高,但有个缺点: 不支持路由排序,会认为是路由冲突。
- 比如: 路由Get("/name")和 Get("/:id") ,一般来说,只要把Get("/name")放在Get("/:id")前面,就是不冲突的。路由模块,会先尝试匹配前面那个,没匹配上,再去匹配后面的。
- 而 gin和echo用的路由模块,会认为这两个路由是冲突的。gin会给出提醒,不让编译通过;echo完全不提醒,冲突就冲突了。。。
两个都不够好。框架的可持续发展
- gin的主创是2个大学生。每年寒暑假就频繁更新,快到期末考试了,就完全不更新了。两人不在的时候,有网友在帮忙热情的维护,但主要是修bug、整理中间件。框架本身的发展,还是靠主创寒暑假爆发。就是这样的框架,连csico都在用。。。
- 好在,gin的代码注释量大,易读性高,便于其他人参与。而且包装中间件,也超级容易。
- 作者本人的态度是,对于一个在github上,start达到5000+的项目,他怎么可能会不去维护。请大家放心使用,到寒暑假了,他自然会去更新。。。
- echo则是主创当前处于活跃状态,并且乐呵呵的想要开发2.0版。由于主创活跃,它自带了一些流行功能,比如websocket, http2, jwt授权。用gin的话,这些功能要自己包装个中间件,虽然也很容易就是了。
- 但echo的问题在于,它的代码毫无注释。作者现在是在劲头上,等3-6个月,在路上看到个穿超短的妹子,热情转移了,很快就会忘记当时代码是怎么写的。没有注释,不但别人不方便接手,自己也懒得再去看,于是慢慢就永不再更新。
- 缺少注释的开源包,大部分都有这个问题。echo最终会不会变成这个结局,我们无从得知。
综上总结
- echo的状态是当下主创本人活跃,框架还不太成熟,适合最轻量级服务;
- gin则是整体成熟、易于调试,但可以预期,框架本身发展不会太快,除非主创大学毕业,从事和golang相关的工作。
- echo的使用方式、命名,都参考了gin,两者很接近,切换框架很容易,所以不用担心选错。
更新
由于echo的路由冲突频繁且没有调试信息,目前不是合理选择。等作者补上了路由冲突检测,那么就还不错。
如果想要回避这种框架的路由冲突,又想享受类似的优秀,neo框架目前最接近.
原文地址:https://www.golangtc.com/t/56a38761b09ecc083100010c
Golang两种MD5加密方式
编程 Rock 发表了文章 0 个评论 6515 次浏览 2015-12-01 19:53
代码
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
)
func main() {
// md5 加密的第一种方法
srcData := []byte("iyannik0215")
cipherText1 := md5.Sum(srcData)
fmt.Printf("md5 encrypto is \"iyannik0215\": %x \n", cipherText1)
// md5 加密的第二种方法
hash := md5.New()
hash.Write(srcData)
cipherText2 := hash.Sum(nil)
hexText := make([]byte, 32)
hex.Encode(hexText, cipherText2)
fmt.Println("md5 encrypto is \"iyannik0215\":", string(hexText))
}
# 执行结果
md5 encrypto is "iyannik0215": b6b20c73e6bc53bc691a6bb559cf9ca9
md5 encrypto is "iyannik0215": b6b20c73e6bc53bc691a6bb559cf9ca9
不同
解释一下两种加密方式的不一样之处.
第一种加密方法:
第一种加密方法所调用的函数
//Source file src/crypto/md5/md5.gofunc Sum(data []byte) [Size]byte
19 // The size of an MD5 checksum in bytes.
20 const Size = 16
130 // Sum returns the MD5 checksum of the data.
131 func Sum(data []byte) [Size]byte {
132 var d digest
133 d.Reset()
134 d.Write(data)
135 return d.checkSum()
136 }
其 [Size]byte 是固定死的.所以说第一种方法返回的是 16长度的数组.
第二种加密方法:
//Source file src/crypto/md5/md5.go这里使用 func New() hash.Hash {} 函数进行生成对象.
50 // New returns a new hash.Hash computing the MD5 checksum.
51 func New() hash.Hash {
52 d := new(digest)
53 d.Reset()
54 return d
55 }
// 这里只放了函数签名部分, 关于函数具体内容这里就不详细复制了.
51 func New() hash.Hash {}
61 func (d *digest) Write(p []byte) (nn int, err error) {}
90 func (d0 *digest) Sum(in []byte) []byte {}
使用 func (d *digest) Write(p []byte) (nn int, err error) {} 方法进行写入要加密的数据.
使用 func (d0 *digest) Sum(in []byte) []byte {} 方法进行数据的加密 看其返回值.
[]byte 可见使用第二种方式加密返回的是 []byte 类型的切片.