通向Golang的捷径【3.编辑器,IDE 和其他工具】

由于 Go 是一种相当年轻的语言, 因此 IDE 的开发仍在进行中, 但有些编辑器已提供了 Go 语言的支持, 同时必须提供跨平台的特性, 在http://go-lang.cat-v.org/text-editors/页面中, 列出了支持 Go 语言的文本编辑器.

3.1 Go 开发环境的基本需求

一个开发环境需要实现一个简单的文本编辑器, 以及在命令行中可运行的编译和链接工具, 以下给出了开发环境应当支持的基本需求:
• 语法高亮: 每种开发环境都会为语法高亮, 提供对应的配置文件或设置文件, 以及不同的着色方案.
• 自动保存: 可对编辑源码进行定时保存.
• 显示行号: 可加速源码的编辑.
• 源码的预览和提纲: 当不同源码文件被打开时, 该功能可加速源码的浏览, 还需要为源码设置书签, 以及选中匹配功能, 跳转到定义的功能, 能方便查找调用函数的原型.
• 良好的查找和替换功能, 这也是预览功能之外, 最应当提供的功能
• 将选中代码, 设定成注释和取消注释功能.
• 编译器错误的定位: 双击错误消息, 可跳转并高亮显示出现问题的代码行.
• 跨平台: 可兼容 Linux,Mac OS X,Windows, 并且开发环境只需安装一次, 就可为不同平台创建可执行程序.
• 最好能免费, 一些开发者希望通过付费, 来获得高性能的开发环境, 这就需要足够的分辨力, 来确认性能的高低.
• 最好能开源.
• 可使用插件: 利用新插件, 可扩展或替换相应的功能.
• 易于使用: IDE 是一个相当复杂的实现, 应当保持尽量小的尺寸.
• 代码片段 (模板): 可快速插入大量的代码片段, 以加速编码, 同时让编码更简单.
• 可创建 Go 语言的项目文件, 以便预览项目中, 所包含的文件和包, 同时能让 Makefile 成为一种配置文件,另外还需要提供编译系统, 以方便项目的编译/链接, 清除和运行, 完成编译的程序可在控制台或是 IDE中运行.
• 调试: 可实现代码调试的断点, 数值检查, 单步执行等功能, 同时有能力实现库代码的单步执行.
• 提供最近文件和项目的访问.
• 编码补全功能: 可完成关键字, 包名, 包中类型和方法名, 自定义的类型名/变量名/ 函数名/方法名, 函数签名的补全.
• 可提供项目代码和包代码的 AST 预览 (AST-view, 一个抽象的语法树).
• 内建 go 语言的工具, 比如 go fmt,go fix,go install,go test 等.
• 集成 go 文档的简便浏览.
• 可在不同的 Go 语言环境中简单切换 (8g,6g, 或是不同的安装目录).
• 使用不同文本格式, 导出源代码, 比如 pdf,html 或是源代码的打印功能.
• 项目模板: 可快速构建不同类型的项目文件, 比如 web 应用,App 引擎项目等.
• 可实现重新配置 (Refactoring)
• 集成版本控制系统, 比如 hg 或 git.
• 集成 Google App 引擎

3.2 编辑器和 IDE

在 Emacs, Vim, Xcode3, KD Kate, TextWrangler, BBEdit, McEdit, TextMate, TextPad, JEdit, SciTE, Nano, Notepad++, Geany, SlickEdit, SublimeText2 编辑器中, 可提供 Go 的语法高亮, 以及其他支持工具的使用.

GEdit 是一个 Linux 文本编辑器, 可创建一个完美的 Go 开发环境 ( http://gohelp.wordpress.com).

SublimeText(http://www.sublimetext.com/dev) 是一个跨平台文本编辑器 ( 支持 Linux,Mac OS X,Windows),使用扩展插件, 可支持多个编程语言, 目前可为 Go 提供一个 GoSublime 插件 (https://github.com/DisposaBoy/
GoSublime), 它能实现代码补全和添加代码片段的功能, 同时还出现了多种 Go 语言的开发环境, 其中一些还支持 Java, 这是因为它是一个收费的编辑器.

NetBeans(商业版) 已为 Go 语言提供了插件, 能实现语法高亮和代码模板 ( http://www.winsoft.sk/go.htm),一个最新的免费插件正在开发中 ( http://www.tunnelvisionlabs.com/downloads/go/).

gogo 是一种 Go 语言的开发环境, 支持 Linux 和Mac(http://www.mikeparr.info/golinux.html).

GoIde(跨平台) 是 IntelliJ IDE 的一个插件 (http://go-ide.com/), 可从 https://github.com/mtoader/google-go-lang-idea-plugin 页面, 下载该插件, 它可提供完美的源码编辑功能, 以及代码补全, 该插件的验证页面为
http://plugins.intellij.net/plugin/?idea&id=5047.

LiteIDE(又称 golangide, 跨平台) 是一个完美的开发环境, 可编辑, 编译和运行 Go 代码, 并能创建 Go 项目, 其中包含了源码的抽象语法树 (AST) 查看器, 以及内建的 make 工具, 从 http://code.google.com/p/golangide/
downloads/list 页面, 可下载该工具.

GoClipse(跨平台) 是 Eclipse IDE 的一个插件 ( http://goclipse.googlecode.com/svn/trunk/goclipse-update-site/), 值得注意的特性是, 可自动创建 makefile, 以及代码补全 (基于 GoCode 实现的文本帮助) 功能.

如果对上述 IDE 都不熟悉, 可选择 LiteIDE, 同时 GoClipse 或 GoIde 也是不错的选择.

基于 GoCode 插件, 可内建代码补全功能 (比如 LiteIDE 和 GoClipse), 使用以下命令, 可安装 gocode:

$ git clone git://github.com/nsf/gocode.git
$ cd gocode
$ export GOROOT=$HOME/go
$ export PATH=$HOME/go/bin:$PATH
$ make install

测试 gocode 的安装结果:
$ gocode status

可得到以下输出:
Server’s GOMAXPROCS == 2
Package cache contains 1 entries
Listing these entries :
name : unsafe (default alias: unsafe)
imports 9 declarations and 0 packages
this package stays in cache forever ( built-in package )

下表比较了之前推荐的三种 IDE, 在目前的发展状态下, 这三种 IDE 的功能最强大, 其中 + 表示该功能可以工作,++ 表示该功能比较强大, 留白表示不支持该功能.

LiteIDE GoClipse GoIde
高亮语法 ++ + +
自动保存 +
行号 + +
书签
选中匹配 +
查找/替换 + ++
跳转到定义
注释/取消注释 +
编译错误的链接 ++ +
跨平台 + +
免费 + +
开源 + +
可使用插件 + +
易用性 ++ +
添加代码片段
可创建项目 + +
代码的折叠效果
构建系统 + +
调试 + +
最近文件和项目的访问 + +
代码补全 + ++
代码抽象语法树的查看 ++ +
内建 go 支持工具 + +
go 文档的浏览 +
不同 go 环境的切换 ++ +
以不同文本格式导出代码 ++ +
项目模板
版本控制系统的集成
Google App 引擎的集成 ++

以下将详细介绍 LiteIDE 和 GoClipse.

3.2.1 LiteIDE

当前版本为 X10, 主页为http://code.google.com/p/golangide/.

LiteIDE 是一种包含插件架构的轻量级 IDE(基于 QT,Kate 和 SciTE), 其中包含了 Go 语言需要的所有特性,并能实现跨平台开发, 同时支持优秀的编辑功能, 代码补全和调试, 该 IDE 还可创建项目, 并在项目的根目录下, 可创建 Makefile, 同时该 IDE 可使用不同的环境文件 (.env) 以及对应的环境变量, 因此能在不同的 Go 开发环境中切换, 比如 32bit 与 64bit 版本的切换, 以及静态版本和周版本的切换.

该 IDE 还可提供代码中抽象语法树的查看, 这使得源码的常量, 变量, 函数, 不同类型的定义, 以及方法, 可进行一个系统化的浏览.

3.2.2 GoClipse

当前版本为 0.2.1, 主页为http://code.google.com/p/goclipse/.

它是 Eclipse IDE 的一个插件, 一个大型 IDE 的启动相当慢, 因为需要运行 Java VM(虚拟机), 同时又可执行大量的内建功能, 对于 Go 语言来说, 它可支持优秀的编辑功能, 代码补全和代码提纲, 项目查看和调试功能.

3.3 调试器

在应用编程中, 需要提供一个良好的调试器, 为了达到这个目标, 大家还在努力, 目前的调试器 Oogle 需要gdb(版本至少为 7) 的支持, 同时 Google Go 开发组在 gc 链接器 (6l,8l) 中, 内建了 GNU 调试器, 也可参考http://blog.golang.org/2010/11/debugging 页面.

在 LiteIDE 和 Goclipse 中, 包含了 gdb 7.1 版本, 如果不使用调试器, 也可使用以下的调试策略:
• 可在相应的代码中, 使用 print 语句 (print/println 和 fmt.Print 函数).
• 在 fmt.Printf 函数中, 可使用以下变量, 获取完整的信息.
%+v 可获得作用域中, 实例的完整输出.
%#v 可获得作用域中, 实例的完整输出, 以及类型名的完整输出.
%T 可获得完整的类型定义.
• 使用 panic 语句 , 可获取堆栈的跟踪信息 (即该语句执行之前的所有函数调用).
• 使用 defer 关键字, 跟踪代码的执行.

3.4 在命令行或 Makefile 中进行 Go 程序的构建和运行

当程序完成编写 (应采用典型的命名规则和编码风格), 可使用 gofmt 实现代码的格式化, 再进行构建 (编译/链接), 如果构建过程 (或称编译期) 未出现错误, 将显示以下信息.
−−−− Build file exited with code 0.

在大多数 IDE 中, 可保存源码文件的最新修改, 再进行构建. 如果构建过程中出现错误, 将显示以下信息:
−−−− Build file exited with code 1,

同时还给出发生错误的代码行号, 如下:
hello_world.go: 6 : a declared and not used

在大多数 IDE 中, 双击错误消息, 可跳转到发生错误的代码行.Go 语言工具不会区分警告和错误, 这里包含了一种理念, 出现警告是因为代码存在误用, 最好能将其视为错误, 以保证最终应用的安全性, 如果执行未完成编译的程序, 将得到以下错误:
−−−− Error run with code File not found, resource error

当程序在运行时状态下执行, 并且完成了正确的执行, 将得到以下输出:
−−−− Program exited with code 0

编译器和链接器可使用-o 选项, 设定可执行文件名, 如果需要将 test.6 编译成 test.go 程序, 可指定一个文件名, 以替代 test.6,
6l -o test test.6

在 Windows 系统中, 可在 run.cmd 或 run.bat 文件中包含以下命令 (在第一行文本中, 包含了 Go 的安装根目录):

set GOROOT=E:\Go\GoforWindows\gowin32_release.r60\go
set GOBIN=$GOROOT\bin
set PATH=%PATH%;$GOBIN
set GOARCH=386
set GOOS=windows
echo off
8g %1.go
8l -o %1.exe %1.8
%1

在 Windows 命令行中, 可使用 run test, 运行 test.go 程序.

在 Linux 和 OS X 系统中, 可使用 Makefile 完成编译和链接 (且无须了解编译器/链接器的类型, 比如 5-,6-或8-), 可使用以下文本, 创建一个 Makefile 文件:

include $(GOROOT)/src/Make.inc
TARG=test
GOFILES=\
	test1.go \
	test2.go \
include $(GOROOT)/src/Make.cmd

将 Makefile 文件的权限改为 777, 再执行该文件 (./Makefile). 在 Makefile 文件的 GOFILES 变量中, 包含了需要编译和链接的所有 go 文件, 文件之间需使用空格进行分隔,TARG 变量给出了可执行文件名, 在命令行中运行 make, 可实现源码文件的编译和链接, 之后可输入./test, 执行该程序. 如果需要在 Makefile 中, 创建自定义变量, 比如 VAR1, 可在 Makefile 文件的变量定义之后, 加入 $(VAR1) 表达式.

在 Go 1 版本中, 可提供两个工具:
• go build: 可实现编译, 以及安装依赖文件和包
• go install: 安装依赖文件和包

可使用 gomake 工具替换 make, 它是 Go 1 发布之前, 已经存在的工具, 如果配置好 $GOROOT, 就可运行 gomake, 用法为gomake [ target … ], 支持的选项如下:
• all: 默认值, 可构建包和命令工具, 但无法安装.
• install: 构建和安装对应的包和命令工具.
• test: 运行测试 (只支持包)
• bench: 运行性能评估程序 (只支持包)
• clean: 从当前目录中, 移除目标文件
• nuke: 清理和清除已安装的包和命令工具

为了提高易用性, 可给出不同的 Makefile 文件, 比如 Makefile_Proj1, Makefile_Proj2 等, 如果需要调用特定的 Makefile 文件, 可使用-f 选项, 比如gomake -f Makefile_Proj1.

在 Makefile 文件中, 包含了代码的格式化, 调用 gofmt, 可将源码风格变更为 gomake 格式, 如下:

format :
	gofmt -w $ (GOFILES)

Windows 的 Makefile 文件

依靠 MINGW(http://www.mingw.org/), 在 Windows 中也可使用 Makefile 文件, 为了运行 Go 工具链 (比如gomake,gotest 等), 必须将 Windows 系统改造成类 Unix 系统, 所以能在 Windows 系统中构建 Go 应用. 同时
MSYS(功能受限) 在 Windows 系统中, 可实现与 MINGW 相似的功能 (https://bitbucket.org/akavel/gowin-env),

下载 gowin_env.zip 并解压, 可生成一个 gowin_env 目录, 其中包含了 msys 子目录和一些批处理文件, 使用文本编辑器, 打开 console.bat 文件, 在其中设定好 GOROOT 环境变量 ( 即 Go 语言的安装目录), 比如:

set GOROOT=E:\Go\GoforWindows\gowin32_release.r57 .1\go

同时在 go_env.bat 文件中, 输入相同的内容, 再双击 console.bat 文件, 则在弹出控制台中, 调用 make 命令,对 Makefile 指定的文件, 进行编译和链接.

为了测试目录中包含的多个文件能否成功编译, 以下给出了一个 Linux 脚本,

例 3.1 gocomp

#!/bin/bash
FILES=~/goprograms/compiletest/*.go
for f in $FILES
do
	echo "Processing $f file ..."
	# take action on each file. $ f stores current file name
	# cat $f
	6g $ f >> compout
done

可将~/goprograms/compiletest/替换成所需的测试目录, 测试结果将附加在当前目录下的 compout 文件中.相似的 Windows 脚本也很容易编写, 比如:
FOR %%X in ( *. go) DO 8g %%X >> compout

它可编译当前目录下的所有 go 文件, 并将编译结果输出到 compout 文件.

3.5 代码格式化

Go 语言创造者不希望在编码风格上, 进行无休止的争论, 相似的争论之前已经出现过, 所以很多编程语言在这类问题上, 消耗了宝贵的开发时间, 因此 Go 语言提供了 go fmt(即 gofmt) 工具, 它可将 Go 代码转换成官方认定的标准风格, 这是一个代码的排版工具, 使用了一种简单方法进行重新配置, 也是 Go 开发中必须使用的一个工具, 同时也希望所有的 Go 开发者都能使用该工具, 在代码编译或检查之前, 请使用 gofmt. 似乎找不到拒绝 gofmt 的理由, 放弃自由风格将带来丰厚的益处, 比如保证 Go 代码的一致性, 更好的可读性, 培养尽快理解他人代码的感觉, 大多数编辑器都内建了该工具.

当然目前的代码规则并不完整, 比如 tab 键和空格键的用法,tab 键的一次点击, 将给出 4 个或 8 个空格, 在实际的代码中, 推荐 4 个空格, 在书籍的打印中, 推荐 8 个空格, 在编辑器中编写代码, 应当使用 tab 而不是空格键.

命令gofmt -w program.go 可格式化 program.go 文件 (省略-w 选项, 完成的格式化将无法保存),gofmt 可用于任意 go 文件, 而命令gofmt map1 可实现递归操作, 可格式化 map1 目录及其子目录中包含的所有 go 文件. 但在代码库中使用该工具时, 将存在一个小变化, 可使用-r 选项, 标记一个规则, 在两个” ”(双引号) 之间, 可给出该规则, 规则的格式为: 匹配规则-> 替换内容, 如下:
gofmt −r ” ( a ) −> a ” –w * . go

在当前目录下的所有 go 文件中, 去掉与 a 相关的单层圆括号 ().
gofmt −r ” a [ n:len(a)] −> a[n:] ” –w *.go

在切片声明中, 清除不需要的 len(a).
gofmt –r ’A.Func1(a,b) −> A.Func2(b,a) ’ –w *.go

使用 Func2 替换 Func1, 同时互换函数包含的参数.从http://golang.org/cmd/gofmt/页面中, 可查找到 gofmt 的更多信息.

3.6 文档化

go doc 可生成 Go 程序和包的文档, 它可提取源码中顶层声明之前的注释, 同时这类注释与声明之间, 不能存在文本行, 由此 go doc 可判断注释和声明之前的关系, 并且 go doc 也作为提供文档的 web 服务器, 从http://golang.org 页面, 可查找到相关的工作流程.

一般格式

• go doc package
可生成包的注释文档, 比如 go doc fmt, 可输出 fmt 包起始处的注释.
• go doc package/subpackage
可生成子包的文档, 比如 go doc container/list.
• go doc package function
可生成包函数的文档, 比如 go doc fmt Printf, 可获得 fmt.Printf() 的用法描述.

只有当 Go 源码处于根目录下 (go/src/pkg), 上述命令才可工作,godoc 命令还包含了其他一些运行选项, 同时godoc 也作为本地服务器, 比如godoc -http=:6060, 可在命令行中, 启动 godoc 服务器, 再打开浏览器, 输入
http://localhost:6060, 在无网络连接的情况下, 可得到一个本地文档服务器. 同时 godoc 也可生成用户程序的文档, 从 http://golang.org/cmd/godoc/页面, 可获得更多的相关信息.

3.7 其他工具

Go 工具集 (http://golang.org/cmd/) 包含的工具, 一部分使用 shell 脚本, 另一部分则使用了 Go 语言, 在 Go 1 版本中, 还包含了以下工具:
• go install(goinstall)
它是一个包安装工具, 并与 Ruby 语言的 rubygems 很相似, 该工具可在标准库之外, 安装其他的包, 它也可实现包源码的格式化, 以便完成包的本地编译和链接,

• go fix(gofix)
它是一个 Go 语言版本的更新工具, 并能自动完成同步更新, 这意味着相同代码则不会更新. gofix 也会区分简单更新, 重复更新和耗时更新, 如果 API 的变更并不是简单的新函数替换, 而是需要人工检查时,gofix 将给出一个警告, 并在警告中给出文件名和对应的行号, 以使开发者能够快速检查和重写代码,当 API 发生变更时,Go 开发组也会使用该工具进行定时更新, 在 Google 内部也会使用该工具, 进行 Go语言版本的更新,go fix 之所以能够在这种条件下工作, 是因为 Go 语言能在标准库的支持下, 将源码解析成抽象语法树, 同时也可将语法树转换成 Go 源码.go fix 可更新当前目录下的所有 go 文件, 并能在输出信息中, 给出发生变换的文件名, 比如 go fix -diff,
可显示与已安装版本不同的其他 Go 版本,go fix -w 更新所有的变更.

• go test(gotest) 是用于单元测试的一个轻量级测试框架,

3.8 性能

基于 Go 开发组在简单算法程序中进行的测试结果,Go 语言的性能通常为 C 语言的 10%-20%, 但这并不属于一个官方测评, 由于 Go 语言的不断发展, 必须定期进行类似的比较, 才能了解 Go 语言的实际性能.

另一个更可靠的信息, 即 Go 语言比 C++ 慢 20%, 如果让 Go 语言运行在更保守的条件下, 并且只提供最低内存需求的 70%, 那么 Go 语言的性能与 Java 或 Scala 相当, 由于实际的应用条件千差万别, 对于 Google 来说, 只要能改善数千台服务器的延时, 对 Go 语言的投资就有意义.

目前的一些主流编程语言, 会运行在一个虚拟机中, 比如 Java JVM, Scala, C# 的.NET CLR 等, 为了改善笨重虚拟机的性能, 因此产生了 JIT 编译器和脚本语言的解析器 (Ruby,Python, Perl,Javascript 等), 当然上述语言的性能都不可能接近于 C/C++ 的性能. 如果 Go 语言比 C++ 慢 20% 的提法成立,Go 语言将比那些无法提供静态类型和静态编译的语言, 快 2-10 倍, 同时内存的效率也可大幅提升.

比较多个编程语言的测评, 需要一定的技巧, 首先测评程序的任务应当一致, 基于不同的编程语言, 应当给出任务的最佳解决方案, 比如在文本处理中, 能处理字节流的语言, 肯定优于只能处理 Unicode 码的语言, 同时测评程序也需要编写, 因此编写者对于不同语言, 应该有不同的理解和经验, 这也将影响最终的测评结果, 因此每个编程语言的测评程序, 必须由精通该语言的开发者完成, 另外在结果统计中, 也应当消除人为影响, 在比较中,还必须考虑一个问题, 在大多数的成熟语言中, 会基于一些特定任务, 对库进行优化, 而 Go 语言还没有经历类似的过程, 为了完成语言的测评, 可关注一个计算机语言的测评游戏 (http://shootout.alioth.debian.org/).

部分测评结果

• 基于简单的 web 服务器应用, 比较 Go 和 Python
Go 原生 http 包的速度, 约为 web.py 的 7-8 倍, 同时 web.go 的性能约为 web.py 的 6-7 倍, 如果在Python web 环境中, 使用 tornado 异步服务器/框架, 性能可好于 web.py, 如果 tornado 的系数在 1.2-1.5之间,Go 将优于 tornado.

• Go 的平均性能约为 Python 3 的 25 倍, 只需要 Python 3 的三分之一内存, 但代码量约为两倍.

• 在 Robert Hundt 的论文 (2011/6) 中, 比较了 C++, Java, Go, Scala, 以及 Go 开发组的反应, 因此基于以下的一些测评结果,Go 开发组进行了对应的调整:
▶ Scala 和 Go 代码比 C++ 和 Java 更加紧凑 (代码量更少).
▶ Go 的编译最快, 通常是 Java 和 C++ 的 5-6 倍, 约为 Scala 的 10 倍.
▶ Go 生成的二进制文件的尺寸最大 (其中需要包含运行时库).
▶ 经过优化的 Go 代码, 可与 C++ 一样快, 比 Scala 快 2-3 倍, 约为 Java 的 10 倍.
▶ Go 语言的内存消耗, 与 C++ 相同, 约为 Scala 的一半, Java 的四分之一.

3.9 与其他语言的交互

3.9.1 与 C 语言的交互

cgo 程序提供了一种 FFI(foreign function interface, 外部函数接口) 机制, 以便在 Go 代码中安全调用 C 库, 在http://golang.org/cmd/cgo 页面中, 给出了 cgo 文档, 同时 cgo 可替代正常的 Go 编译器, 它可将 Go 文件和 C 文件, 合并到一个 Go 包中, 因此可从一个包中, 调用 C 代码.

为了实现与 C 的交互, 必须在 Go 程序中导入:

import "C"
import "unsafe"

在 Go 代码中, 放入对应的 C 库名, 可将其作为注释, 如下:

// #include <stdio.h>
// #include <stdlib.h>
import "C"

import ”C”上述的”C” 并非指 C 标准库构成的一个包, 而是 cgo 可解析的一个特殊名称, 并视为引入了一个 C 的名字空间, 在这个名字空间中, 包含了 C 类型, 比如 C.uint, C.long 等, 以及从 libc 中调用函数, 比如 C.random(). 同时 Go 变量可在变量类型与 C 类型之间, 进行相互转换,

var i int
C.uint(i)  // 将 Go 的 int 类型转换成 C 的 unsigned int 类型
int(C.random()) // 将C类型(random()可返回long类型)转换成Go的int类型

在以下程序中, 包含了两个 Go 函数 Random() 和 Seed(), 而这两个函数等价于 C.random() 和 C.srandom().

例 3.2 c1.go

package rand
// #include <stdlib.h>
import "C"
func Random() int {
	return int(C.random())
}
func Seed(i int) {
	C.srandom(C.uint(i))
}

在 C 类型中, 并不存在明确的字符串类型, 为将 Go 字符串转换成 C 类型, 可使用 C.CString(s), 相反的操作,可使用 C.GoString(cs), 其中 cs 即为 C 的字符串类型. 另外应当注意,C 代码的内存分配, 并不知晓 Go 包含了内存管理, 所以开发者为了实现 C 变量的内存释放, 需使用 C.free, 如下:
defer C.free(unsafe.Pointer(Cvariable))

上述代码行可跟随 C 的内存分配语句, 这将使内存释放不会被忘记, 以下代码中, 包含了 Go 函数 Print(), 它可将字串打印到控制台 (这一功能依赖于 C 函数 fputs), 以显示出内存释放的相关信息.

例 3.3 c2.go

package print
// #include <stdio.h>
// #include <stdlib.h>
import ”C”
import ”unsafe”
func Print(s string) {
	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))
	C.fputs(cs,(*C.FILE)(C.stdout))
}

构建 cgo 包

创建了一个特定包的 Makefile 也可在这里使用, 这里启用了变量 GOFILES, 而是在 CGOFILES 变量中, 列出了需使用 cgo 进行编译的文件, 比如例 3.2 将使用以下 Makefile, 被编译到一个包中, 这里可使用gomake 或 make.

include $(GOROOT)/src/Make.inc
TARG=rand
CGOFILES=\
	c1.go \
include $(GOROOT)/src/Make.pkg

3.9.2 与 C++ 的交互

在 Linux 系统下,Go 语言可使用 SWIG(Simplified Wrapper and Interface Generator, 简单的封装器和接口生成器) 实现 C++/C 代码的调用, 使用 SWIG 需要一些条件:
• 为需要封装的库, 编写 SWIG 接口文件.
• SWIG 必须生成 C 的端口 (stub) 函数.
• 使用 cgo, 才可完成调用.
• Go 文件的操作可自动完成.

这类接口可处理重载, 多重继承, 并允许为 C++ 抽象类提供一个 Go 实现, 目前 SWIG 存在的问题是, 无法完全理解 C++, 比如无法解析 TObject.h.

在这里插入图片描述

发布了80 篇原创文章 · 获赞 10 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/osoon/article/details/103741494