"文档概要 该文档介绍了 Wide 的设计原理与核心实现。如果您要读 Wide 的源码或者要进行修改、二次开发等,请先仔细阅读该文档。 架构 本章将介绍 Wide 的架构概要,说明 Wide 是如何完成一个 IDE 的核心功能。 构建 & 运行 [图片] 一个浏览器 tab 对应一个 Wide 会话 通过 Web .."

Wide 开发指南

本贴最后更新于 254 天前,其中的信息可能已经事过境迁

文档概要

该文档介绍了 Wide 的设计原理与核心实现。如果您要读 Wide 的源码或者要进行修改、二次开发等,请先仔细阅读该文档。

架构

本章将介绍 Wide 的架构概要,说明 Wide 是如何完成一个 IDE 的核心功能。

构建 & 运行

  1. 客户端浏览器发送 Build 请求
  2. 服务器使用 os/exec 执行 go build 命令
    2.1. 生成可执行文件
  3. 客户端浏览器发送 Run 请求
  4. 服务器使用 os/exec 执行文件
    4.1. 生成进程
    4.2. 运行结果输出到 WebSocket 通道
  5. 客户端浏览器监听 ws.onmessage 到消息后做展现

代码辅助

  1. 浏览器客户端发送代码辅助请求
  2. Handler 根据请求对应的 HTTP 会话获取用户工作空间
  3. 执行 gocode/ide_stub(gotools) 命令
    3.1 设置环境变量(${GOPATH} 为用户工作空间路径)
    3.2 gocode 命令需要设置参数 lib-path

关键设计

本章将介绍 Wide 中的关键设计,以及一些实现细节。

工作空间

Wide 是一个多用户的集成开发环境,每个用户的工作空间是完全隔离的:

例如在执行“构建 & 运行”时,Wide 会设置命令 go build 执行的 $GOPATH 为用户的工作空间,这样编译过程就是在该用户的工作空间中进行,保证其隔离性。

会话

在 UI 上存在两种 tab:浏览器 tab;编辑器 tab。

用户可以在一个浏览器 tab 中打开多个编辑器 tabs,但输出窗口只有一个。这意味着一个浏览器 tab 只能有一个正在运行的用户代码的程序进程。
需要同时运行多个程序进程的场景可以通过打开多个浏览器 tabs 达成。

WebSocket

WebSocket 用于后端推送数据给前端:

通道和会话一对一关联,也就是说如果用户新开浏览器 tab,则新建通道和其关联。

其中 _ 会话通道 _ 用于会话管理,后面会单独介绍。

事件与通知

每个会话都有一个对应的事件队列,当接收到事件时取出该事件并转为通知,再通过通知窗口通道推送给前端。

还存在一个全局事件队列,入队的事件将分发到每个用户的事件队列中,以便进行通知广播。

通知中的消息需要国际化处理。在语言配置文件中以 notification_ 为前缀,事件代码(event code)为后缀的项即通知消息。

代码辅助

代码辅助功能满足工作空间隔离。

会话管理

本章我们将说明 Wide 会话的生命周期以及和它相关的服务器端状态管理。

服务器端状态

一般 Web 应用的服务器端都是“无状态”的设计:一次 HTTP 请求 - 响应完成一个操作,下一个操作和这次的操作没有任何直接的关联。

比如“用户注册”一般都是在一个请求的生命周期内完成,即使不能完成,也需要服务器端持久化状态,“下一步”时查询该状态并继续进行操作。

这样的“无状态”设计这主要是因为:

Wide 会话

Wide 不是一个 Web 网站,它对服务器端的状态管理有特殊的需求。

生命周期

在前面我们提到过 Wide 会话和浏览器 tab 的关系,这定义了 Wide 会话的生命周期和浏览器 tab 是一致的:

会话状态

一个 Wide 会话包含如下信息:

销毁一个会话时,需要将其相关的资源回收,避免泄漏。

实现

服务器端使用 WebSocket 建立同 tab 的通讯通道,通道关闭时销毁服务器端会话。

会话还原

当再次打开 IDE 时我们需要还原最近一次的“会话内容”:

准实时保存

当一个用户存在有多个会话(打开多个浏览器 tabs)时,还是以该策略进行保存(顺时覆盖)。

编码规范

本章描述了 Wide 项目中编码时的一些细节事项。

关于 Golang 公共的编码规范请参考《Golang 编码规范》

注释

必须遵守:

尽量遵守(处女座特质):

示例:

// HTTP Handler 包装.
// 完成共性处理:
//  1. panic recover
//  2. 请求计时
func handlerWrapper(f func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
	handler := panicRecover(f)
	handler = stopwatch(handler)

	return handler
}

Handler 包装

main.go 中加入新的 HTTP Handler 时需要使用 handlerWrapper 函数进行包装,以便做一些共性处理:

  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    25 引用 • 186 回帖 • 515 关注
  • 文档
    51 引用 • 912 回帖 • 1 关注
  • 架构

    我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。

    64 引用 • 322 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    264 引用 • 1075 回帖 • 772 关注
回帖   
请输入回帖内容...