Skip to content

打造属于自己的本地 Go Playground,但不止于此

· 9 min
TL;DR

如果你羡慕使用 Jupyter Notebook 的人轻松将 Python 代码嵌入文档,并动态的展示其结果,那么你其实也可以应用到 Golang 上。

本文详细介绍如何在 Jupyter Notebook 中添加 Go 语言支持,实现类似 Go Playground 的本地开发环境。从安装配置 Gophernotes kernel,到解决 Windows 系统下的实现问题,再到将 Jupyter 笔记本集成到 Hexo 博客中的多种方案对比。文章还分享了 VS Code 与 Jupyter 的整合技巧,为 Go 开发者提供了一个交互式编程与文档展示的全新解决方案。

熟悉 Python 的人应该知道 Jupyter Notebook,它是一种交互式文档(笔记本)。重要的是,它允许在文档中插入代码、文本、数学公式等,并将结果动态展示,或者可视化。说实话,用过的都知道这是一个很好的功能。 还有 Jupyter Lab,它是新版本的 Jupyter Notebook,功能更丰富一些,但是它们核心功能是一样的。所以基本上我们可以不加区分地使用它们。

Jupyter Notebook 一开始主要是为了科学计算并演示方便,而 Jupyter 拆开分别代表了三种语言:Julia(Ju)Python(pyt)R(er) ,它们都跟数学计算密切相关。

它产生于这样的一类场景:当你有了一个 idea,或者复杂的想法,你在笔记本上写下它们,然后又写了一些代码,用来演示、验证你的想法。写完后,你期望笔记本马上执行代码,并展示出结果。你的想法描述里面可能包含数学公式、图片,你的代码可能会有复杂的代数运算,或者会输出数学图形。这些集中到一起,都不是传统的编程工具轻易做到的,但是又存在于很多实际的需求场景中,于是就有了 Jupyter Notebook。

安装 Jupyter#

方式很简单,假设已经安装了 Python3.0+ 因为这是 Jupyter 的基本依赖,那么:

pip install jupyter

运行 Jupyter#

在终端执行命令:

jupyter notebook

到此为止可以使用 Jupyter notebook 了,但默认支持在里面运行 Python 代码,我们的目标是运行 Golang 代码。

根据 文档 是支持 Go kernel 的,这里 Kernel 可以理解为对语言的支持。

image.png

我选择 Gophernotes 这个库作为 Jupyter notebook 的 Go kernel。

安装 go kernel#

阅读这个库的 README.md 文档中 installation 部分的步骤,发现关键步骤是两步:1. 把 gophernotes 库中 kernel/ 目录下的文件全部复制到 jupyter 的 kernels/ 的目录下; 2. 修改 kernel/ 目录中 .json 配置文件的读写权限,并将里面的路径修改为 gophernotes 二进制文件的路径。

以我的 Windows 电脑为例:

  1. 首先安装 gophernotes:
Terminal window
git clone https://github.com/gopherdata/gophernotes
cd gophernotes
git checkout -f v0.7.5
go install
  1. 根据 go env GOPATH 找到 gophernotes 包的位置: image.png

  2. 找到 jupyter kernels/ 目录的位置,在里面新建 gophernotes/ 目录: image.png

  3. 将步骤 2 中 kernel/ 目录中的文件全部复制到步骤 3 中 gophernotes/ 目录中。后面的修改都在这个目录中。

  4. 修改 kernel.json.in、kernel.json 文件的权限,使其有写的权限

  5. 修改 kernel.json.in、kernel.json 文件的内容,如下:

{
    "argv": [
        "D:\\Software\\Go\\bin\\gophernotes.exe",
        "{connection_file}"
    ],
    "display_name": "Go",
    "language": "go",
    "name": "go"
}

主要是在 argv 参数列表中指定 gophernote 执行文件的路径。

重新启动 Jupyter notebook,点击 New 按钮,可以看到: image.png

至此就算成功在 Jupyter Notebook 中添加 Go kernel 了。

Jupyter Notebook 的效果如下:

在 hexo 博客中显示 Jupyter Notebook 的内容#

查了一下资料,要在 hexo 博客中显示 Jupyter Notebook 的内容,也就是要实现如何渲染 .ipynb 类型的文件。目前看到的大致有两种思路:

a. 在 Github 上创建一个公开仓库,将本地 .ipynb 文件上传上去 (类似于图床仓库),将该仓库中的文件链接分享到 nbviewer 网站上,获得一个新的公开链接,将该链接嵌入到 hexo 博客文本里去。

b. 使用 npm 插件 hexo-jupyter-notebook, 在本地将 .ipynb 文件转换成 html 文件,然后嵌入到博客里。

由于我既不想另外再创建 github 仓库专门存放 .ipynb 文件,也不想使用第三方服务 nbviewer,所以就选择了第二种方案。

但是方案二有坑。

坑一:

Terminal window
npm install hexo-jupyter-notebook

通过这个方式从 npm 仓库下载的插件无法正常运行。打开官网: image.png

7 年前的插件,一直没更新,Homepage 链接 404。

但没关系,先试下能不能用。在执行 hexo g 命令时会进行转换,但出错: SharedScreenshot.jpg

看起来这个插件不怎么可靠。快要放弃时,决定看下在本地 node_modules/ 中它的源码。还好代码不多,最后”hack”一下,将这个 bug 暂时消除 —— -其实就是注释掉 main.py 源码中 html_exporter.template_file = 'full' 这一行即可。

坑二:

既然使用 npm 安装这个插件不可靠,看下 Github 上有没有。 还真有:https://github.com/qrsforever/hexo-jupyter-notebook

看了一下,这其实跟前面 npm 包是同一个作者,只不过他 7 年前上传到 npm 仓库后,又改了 Github 的用户名,所以会导致原来的 homepage link 失效。 这个仓库的代码比 npm 提供的包更新,可靠性应该更强一点吧。 要使用也很简单,删掉旧的,将仓库克隆到本地 node_modules/ 目录下即可。结果执行并不顺利,还是有 bug。

最后,跟前面一样,“hack” 一下,注释掉一行代码,这个插件才能跑通:

diff --git a/main.py b/main.py
index 5eee609..68a5a9f 100644
--- a/main.py
+++ b/main.py
@@ -27,7 +27,7 @@ def main(asset_dir, jupyter_file, inc_height):
if not os.path.exists(jupyter_file):
dn = os.path.dirname(asset_dir)
if os.path.exists(dn + ".md"):
- dn = os.path.dirname(dn)
+ # dn = os.path.dirname(dn)
jupyter_file = os.path.join(dn, jupyter_file)
else:
print("not found: " + os.path.join(asset_dir, jupyter_file))

本质上 hexo-jupyter-notebook 插件是利用 nbconvert 库将 .ipynb 文件转换为 .html 文件,并添加一些样式对渲染结果进行修饰。 而 nbconvert 库的安装前提需要依赖 pandoc,所以使用 hexo-jupyter-notebook 插件,需要先安装依赖:

Terminal window
choco install pandoc
pip install nbconvert

注意 choco 命令是 Windows 上的包管理工具,详情见这篇文章:Windows 上居然也有包管理工具?

至此,在 hexo 博客里面显示 Jupyter Notebook 内容的问题初步解决了。

回到主题,有了 Go kernel 的支持,我们相当于就有了自己的本地 Go Playground,可以很方便的运行小型的 Go 代码片段,用于演示语言相关的特性,便于学习,非常实用。 当然,在 Windows 上 gophernotes 还存在一些不足和限制。

在 VS Code 中使用 Jupyter Notebook#

在运行 Jupyter Notebook 时,会跳转到浏览器打开一个新页面,所以可以认为它是基于浏览器的 web 应用。但是我们也可以不这么玩,在 VS Code 上有 Jupyter 插件,我安装了 Jupyter, Jupyter Notebook Renderers,这样就可以在 VS Code 里面愉快地使用 Jupyter notebook 的功能了。

打脸更新#

  1. 已经使用 GoNB 作为 go kernel 了。

  2. 已经直接使用 nbviewer 网站进行 .ipynb 文件渲染了,使用 hexo-jupyter-notebook 或者 hexo-ipynb 有坑。