【Free Style】如何使用Go的so发布库

举报
赵志强 发表于 2017/11/17 16:35:20 2017/11/17
【摘要】 Go默认使用的源码发布的模式,但是使用源码发布可能会遇到这样那样的问题和限制。Go同样是提供了一种使用so发布的方式。下面会关于,开发者如何发布so,以及使用者如何使用so进行详细说明。工程树.├── common│ ├── makefile│ └── src│ └── sum│ └── pack.go├── developer1│ ├── makefi

Go默认使用的源码发布的模式,但是使用源码发布可能会遇到这样那样的问题和限制。Go同样是提供了一种使用so发布的方式。下面会关于,开发者如何发布so,以及使用者如何使用so进行详细说明。

工程树

.
├── common
│   ├── makefile
│   └── src
│       └── sum
│           └── pack.go
├── developer1
│   ├── makefile
│   └── src
│       ├── pack1
│       │   └── pack1.go
│       └── sum
│           └── sum.go
├── developer2
│   ├── makefile
│   └── src
│       ├── pack2
│       │   └── pack2.go
│       └── sum
│           └── sum.go
└── manager
       ├── makefile
       └── src
              ├── main
              │    └── main.go
              ├── pack1
              │    └── pack1.go
              └── pack2
                    └── pack2.go

其中common中的sumdeveloper1开发的pack1developer2开发的pack2共同使用的包,managermain使用pack1pack2两个包。所以,根据这样的逻辑关系,需要common发布一个sum包的libsum.sopack1pack2需要各自拿到这个libsum.so,并发布libpack1.solibpack2.so。最后main需要拿到libsum.solibpack1.solibpack2.so

sum的编译

该工程的目录树为

.
└── common
       ├── makefile
       └── src
             └── sum
             └── pack.go
package sum
func Sum(x, y int) int {
     return x + y
}

sum包的编写如上面代码所示,定义一个package sum,并在里面定义了一个函数Sum。该包的编译如下:

GOPATH=$(shell pwd) go install -buildmode=shared -linkshared std
GOPATH=$(shell pwd) go install -buildmode=shared -linkshared sum

第一行为编译准备一些标准包设置,第二行为编译sum包。注意,第一行一定不能缺少。此时,会在工程下增加pkg节点,此时目录树为:

.
├── makefile
├── pkg
│   └── linux_amd64_dynlink
│       ├── libsum.so
│       ├── sum.a
│       └── sum.shlibname
└── src
      └── sum
             └── pack.go

生成的libsum.sosum.a以及sum.shlibname都需要发布出去。sum.shlibname的内容很简单。

libsum.so

pack1/pack2的编译

pack1pack2的编译类似,以pack1为例,在拿到sum的相关包之后,目录树如下:

.
├── makefile
├── pkg
│   └── linux_amd64_dynlink
│       ├── libsum.so
│       ├── sum.a
│       └── sum.shlibname
└── src
       ├── pack1
       │     └── pack1.go
       └── sum
              └── sum.go

此时目录树中的pkg是直接从common中拷贝过来的,不再赘述。src下的pack1为实际开发的pack1包主体,其实现如下:

package pack1
import "sum"
func Sum(x, y int) int {
     return sum.Sum(x, y) + 1
}

对于sum的使用,直接使用import即可。和正常编写的Go程序并没有太大区别。此处,使用so文件与C中不同的是,需要在于pack1平行的位置建立一个sum文件夹,并新建sum.go文件,其中里面需要填入如下代码:

//go:binary-only-package 

package sum

这两行会告诉编译器,此处为sum包,并只提供binary编译。至此,pack1的编译准备完成,编译命令如下所示:

GOPATH=$(shell pwd) go install -buildmode=shared -linkshared std
GOPATH=$(shell pwd) go install -buildmode=shared -linkshared pack1

编译命令与sum包的类似,在此不作赘述。此时,pack1的目录树为:

.
├── makefile
├── pkg
│   └── linux_amd64_dynlink
│       ├── libpack1.so
│       ├── libsum.so
│       ├── pack1.a
│       ├── pack1.shlibname
│       ├── sum.a
│       └── sum.shlibname
└── src
      ├── pack1
      │     └── pack1.go
      └── sum
             └── sum.go

pkg目录中,多了pack1的相关信息。

main的编译

mainpack1pack2的使用者。分别把sumpack1pack2里面pkg下面的相关文件迁移过来,此时目录树为:

.
├── makefile
├── pkg
│   └── linux_amd64_dynlink
│       ├── libpack1.so
│       ├── libpack2.so
│       ├── libsum.so
│       ├── pack1.a
│       ├── pack1.shlibname
│       ├── pack2.a
│       ├── pack2.shlibname
│       ├── sum.a
│       └── sum.shlibname
└── src
       ├── main
       │     └── main.go
       ├── pack1
       │     └── pack1.go
       └── pack2
              └── pack2.go

其中main/main.go的代码为:

package main
import "pack1"
import "pack2"
func main() {
     println(pack1.Sum(1,2))
     println(pack2.Sum(1,2))
}

pack1使用sum类似,同样需要建立于main平级的两个目录pack1pack2。以pack1为例,其代码为:

//go:binary-only-package

package pack1

编译命令为:

GOPATH=$(shell pwd) go build -linkshared -o main main

运行结果为:

./main
4
5

说明

另外,使用这种shared模式,默认是打开cgo标记的,所以可以在这种模式下使用cgo相关的操作。:)
有问题请espace我, From 编译器与编程语言实验室。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。