GO 入门指南
  • README
  • 开始
    • 前言
  • 第一部分:学习 Go 语言
    • 第1章:Go 语言的起源,发展与普及
      • 起源与发展
      • 语言的主要特性与发展的环境和影响因素
    • 第2章:安装与运行环境
      • 平台与架构
      • Go 环境变量
      • 在 Linux 上安装 Go
      • 在 Mac OS X 上安装 Go
      • 在 Windows 上安装 Go
      • 安装目录清单
      • Go 运行时(runtime)
      • Go 解释器
    • 第3章: 编辑器、集成开发环境与其它工具
      • Go 开发环境的基本要求
      • 编辑器和集成开发环境
      • 调试器
      • 构建并运行 Go 程序
      • 格式化代码
      • 生成代码文档
      • 其它工具
      • Go 性能说明
      • 与其它语言进行交互
  • 第二部分:语言的核心结构与技术
    • 第4章:基本结构和基本数据类型
      • 文件名、关键字与标识符
      • Go 程序的基本结构和要素
      • 常量
      • 变量
      • 基本类型和运算符
      • 字符串
      • strings 和 strconv 包
      • 时间和日期
      • 指针
    • 第5章:控制结构
      • if-else 结构
      • 测试多返回值函数的错误
      • switch 结构
      • for 结构
      • Break 与 continue
      • 标签与 goto
    • 第6章:函数(function)
      • 介绍
      • 函数参数与返回值
      • 传递变长参数
      • defer 和追踪
      • 内置函数
      • 递归函数
      • 将函数作为参数
      • 闭包
      • 应用闭包:将函数作为返回值
      • 使用闭包调试
      • 计算函数执行时间
      • 通过内存缓存来提升性能
    • 第7章:数组与切片
      • 声明和初始化
      • 切片
      • For-range 结构
      • 切片重组(reslice)
      • 切片的复制与追加
      • 字符串、数组和切片的应用
    • 第8章:Map
      • 声明、初始化和 make
      • 测试键值对是否存在及删除元素
      • for-range 的配套用法
      • map 类型的切片
      • map 的排序
      • 将 map 的键值对调
    • 第9章:包(package)
      • 标准库概述
      • regexp 包
      • 锁和 sync 包
      • 精密计算和 big 包
      • 自定义包和可见性
      • 为自定义包使用 godoc
      • 使用 go install 安装自定义包
      • 自定义包的目录结构、go install 和 go test
      • 通过 Git 打包和安装
      • Go 的外部包和项目
      • 在 Go 程序中使用外部库
    • 第10章:结构(struct)与方法(method)
      • 结构体定义
      • 使用工厂方法创建结构体实例
      • 使用自定义包中的结构体
      • 带标签的结构体
      • 匿名字段和内嵌结构体
      • 方法
      • 类型的 String() 方法和格式化描述符
      • 垃圾回收和 SetFinalizer
    • 第11章:接口(interface)与反射(reflection)
      • 接口是什么
      • 接口嵌套接口
      • 类型断言:如何检测和转换接口变量的类型
      • 类型判断:type-switch
      • 测试一个值是否实现了某个接口
      • 使用方法集与接口
      • 第一个例子:使用 Sorter 接口排序
      • 第二个例子:读和写
      • 空接口
      • 反射包
      • Printf 和反射
      • 接口与动态类型
      • 总结:Go 中的面向对象
      • 结构体、集合和高阶函数
  • 第三部分:Go 高级编程
    • 第12章:读写数据
      • 读取用户的输入
      • 文件读写
      • 文件拷贝
      • 从命令行读取参数
      • 用 buffer 读取文件
      • 用切片读写文件
      • 用 defer 关闭文件
      • 使用接口的实际例子:fmt.Fprintf
      • JSON 数据格式
      • XML 数据格式
      • 用 Gob 传输数据
      • Go 中的密码学
    • 第13章:错误处理与测试
      • 错误处理
      • 运行时异常和 panic
      • 从 panic 中恢复(Recover)
      • 自定义包中的错误处理和 panicking
      • 一种用闭包处理错误的模式
      • 启动外部命令和程序
      • Go 中的单元测试和基准测试
      • 测试的具体例子
      • 用(测试数据)表驱动测试
      • 性能调试:分析并优化 Go 程序
    • 第14章:协程(goroutine)与通道(channel)
      • 并发、并行和协程
      • 协程间的信道
      • 协程的同步:关闭通道-测试阻塞的通道
      • 使用 select 切换协程
      • 通道、超时和计时器(Ticker)
      • 协程和恢复(recover)
      • 新旧模型对比:任务和worker
      • 惰性生成器的实现
      • 实现 Futures 模式
      • 复用
      • 限制同时处理的请求数
      • 链式协程
      • 在多核心上并行计算
      • 并行化大量数据的计算
      • 漏桶算法
      • 对Go协程进行基准测试
      • 使用通道并发访问对象
    • 第15章:网络、模版与网页应用
      • tcp 服务器
      • 一个简单的 web 服务器
      • 访问并读取页面数据
      • 写一个简单的网页应用
      • 确保网页应用健壮
      • 用模板编写网页应用
      • 探索 template 包
      • 精巧的多功能网页服务器
      • 用 rpc 实现远程过程调用
      • 基于网络的通道 netchan
      • 与 websocket 通信
      • 用 smtp 发送邮件
  • 第四部分:实际应用
    • 第16章:常见的陷阱与错误
      • 误用短声明导致变量覆盖
      • 误用字符串
      • 发生错误时使用 defer 关闭一个文件
      • 何时使用new()和make()
      • 不需要将一个指向切片的指针传递给函数
      • 使用指针指向接口类型
      • 使用值类型时误用指针
      • 误用协程和通道
      • 闭包和协程的使用
      • 糟糕的错误处理
    • 第17章:模式
      • 逗号 ok 模式
      • defer 模式
      • 可见性模式
      • 运算符模式和接口
    • 第18章:出于性能考虑的实用代码片段
      • 字符串
      • 数组和切片
      • 映射
      • 结构体
      • 接口
      • 函数
      • 文件
      • 协程(goroutine)与通道(channel)
      • 网络和网页应用
      • 其他
      • 出于性能考虑的最佳实践和建议
    • 第19章:构建一个完整的应用程序
      • 简介
      • 短网址项目简介
      • 数据结构
      • 用户界面:web 服务端
      • 持久化存储:gob
      • 用协程优化性能
      • 以 json 格式存储
      • 多服务器处理架构
      • 使用代理缓存
      • 总结和增强
    • 第 20 章:Go 语言在 Google App Engine 的使用
      • 什么是 Google App Engine?
      • 云上的 Go
      • 安装 Go App Engine SDK:为 Go 部署的开发环境
      • 建造你自己的 Hello world 应用
      • 使用用户服务和探索其 API
      • 处理窗口
      • 使用数据存储
      • 上传到云端
    • 第 21 章:真实世界中 Go 的使用
      • Heroku:一个使用 Go 的高度可用一致数据存储
      • MROffice:一个使用 Go 的呼叫中心网络电话 (eBook/VOIP) 系统
      • Atlassian:一个虚拟机群管理系统
      • Camilistore:一个可寻址内容存储系统
      • Go 语言的其他应用
  • 附录
    • 其他
      • 关于本文16.10.2小结糟糕错误处理的一些见解
    • A 代码引用
    • B 有趣的 Go 引用
    • C 代码示例列表
      • 目录
      • 第2章示例
      • 第3章示例
      • 第4章示例
      • 第5章示例
      • 第6章示例
      • 第7章示例
      • 第8章示例
      • 第9章示例
      • 第10章示例
      • 第11章示例
      • 第12章示例
      • 第13章示例
      • 第14章示例
      • 第15章示例
      • 第16章示例
      • 第19章示例
      • 第20章示例
    • D 书中的包引用
    • E 书中的工具引用
    • F 常见问题解答
    • G 习题答案
      • 第4章答案
      • 第5章答案
      • 第6章答案
      • 第7章答案
      • 第8章答案
      • 第9章答案
      • 第10章答案
      • 第11章答案
      • 第12章答案
      • 第13章答案
      • 第14章答案
      • 第15章答案
      • 第16章答案
      • 第19章答案
      • 第20章答案
    • H 参考文献
Powered by GitBook
On this page
  • 20.4.1 映像结构 (map-structure):创造一个简单的 http-handler
  • 20.4.2 创建配置文件 app.yaml
  • 20.4.3 迭代开发
  • 20.4.4. 与 GoClipse IDE 的集成
  • 链接

Was this helpful?

  1. 第四部分:实际应用
  2. 第 20 章:Go 语言在 Google App Engine 的使用

建造你自己的 Hello world 应用

Previous安装 Go App Engine SDK:为 Go 部署的开发环境Next使用用户服务和探索其 API

Last updated 2 years ago

Was this helpful?

现在让我们建造一个像 中的 demo 一样的应用,但这次我们会探索得更深一些。

20.4.1 映像结构 (map-structure):创造一个简单的 http-handler

创建一个目录,并给它起一个你的应用程序特有的名字,如:helloapp。这个应用程序的所有文件都在这个目录中。在这个目录中再创建一个名为 hello 的目录。这将包含我们的 hello 包的 Go 源代码文件。然后在 hello 目录下,创建一个名为 helloworld2.go 的文件,并赋予其以下内容(事实上与上文中的 demo 应用几乎相同):

:

package hello

import (
	"fmt"
	"net/http"
)

func init() {
	http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Hello, world!")
}

注意包的名称:在编写独立的 Go 程序时,我们会把这段代码放在 package main 中,但 Go GAE Runtime 提供了 main 包和 HTTP Listener,所以你应该把你的代码放在你选择的包中,此时指的是 hello 包。其次,由于 Go App Engine 应用程序通过 Web 服务器与外部世界进行通信,所以编写这些应用程序非常像编写独立的 Go Web 应用程序(见)。所以我们导入 http 包,并为我们的应用程序中使用的不同url 模式定义处理函数。我们没有 main() 函数,所以处理程序的设置必须移到 init() 函数中去。另外,网络服务器本身的启动是由 GAE 为我们完成的。我们的 Go 包 hello 对任何请求的响应是发送一个包含 "Hello, world!"的消息。

20.4.2 创建配置文件 app.yaml

所有的 GAE 应用程序都需要一个 yaml 配置文件 app.yaml,它包含了 GAE 的应用程序元数据(yaml 是一种文本文件格式,经常用于开源项目,更多信息见 www.yaml.org)。另外,这个文件告诉 App Engine 服务要使用哪个运行时,哪些 URL 应该由我们的 Go 程序处理。你可以从演示程序中复制一个 app.yaml 文件,把它放在映像 helloapp 里面,并删除 favicon.ico 的 handler。

应用程序的映像/文件结构应该如下:

helloapp\ 	// map of the GAE application
app.yaml 	// configuration file
hello\ 		// map containing the source files
helloworld2.go

只有app.yaml是必须的名字,映像、Go文件和包的名字可以有不同的选择,但按照惯例,它们的名字是一样的或类似的,根映像的后缀是 app。 app.yaml 由 AppEngine 读取和解释,AppEngine 以下时间段内托管和执行你的程序:

  • 当您将您的应用程序上传到 AppEngine 以使其被托管。

  • 当它被执行时。

  • 当用户访问它时。

它可以包含注释,前面有一个 #,并包含以下语句:

application: helloworld
version: 1
runtime: go
api_version: 3

# routing-table: routing of different urls to different types of handlers
handlers:
- url: /.*
  script: _go_app

app.yaml 中的 application: value helloworld 是您的应用程序标识符。这个值在开发过程中可以是任何东西;以后在向 App Engine 注册您的应用程序时,您将选择一个唯一的标识符(在所有 GAE 应用程序中唯一)并更新这个值。

version 表示您的应用程序正在运行的版本:事实上,GAE 可以并行地运行您的应用程序的几个版本,但其中一个必须被指定为默认版本。它可以包含字母数字字符,以及连字符。因此,你可以运行一个测试版本,如T2-31 和一个生产版本 P2-1。

runtime 是编写应用程序的语言(其他允许的值是 Java 和 Python)。如果你在上传应用软件的新版本之前调整它,App Engine 将保留以前的版本,并让你使用管理控制台回退到以前的版本。

api_version 是本 SDK 中使用的 Go API 的版本;它们可能与以前的版本不兼容。你可以在以前的 api_version SDK 中构建你的应用程序的早期版本;如果 GAE 仍然允许,它们可以继续运行,但通常有一个时间限制,而你应该将你的应用程序更新到新的api版本:bin map中的gofix工具可能能够完成大部分所需的更新。

handler 部分是循环表 (routing table):它告诉 GAE 如何将发送到服务器上的请求映射到代码中。对于每一个传入的请求 url 模式(本地开发时在 http://localhost:8080/ 之后的部分,在云端运行时在 http://appname.appspot.com/ 之后的部分)与 url 后面的正则表达式相匹配。

对于第一个匹配的 url 模式,相应的脚本会被执行。在我们的例子中,每一个路径与正则表达式 /.* 相匹配的 URL 请求(即:所有 URL)都应该由 Go 程序处理。_go_app 值是 dev_appserver.py 识别的一个神奇字符串;生产的 App Engine 服务器会忽略它。

如果你看一下演示的 helloworld 应用程序的 app.yaml 文件,你会发现它在处理程序中包含一个初始部分:

handlers:
- url: /favicon\.ico
  static_files: favicon.ico
  upload: favicon\.ico
- url: /.*
  script: _go_app

一些文件 (static_files) ,如图片,不会改变(在这个例子中是图片favicon.ico)。这些文件可以放在不同的 AppEngine 服务器上的一种共同缓存中,使它们能够更快地提供给用户。如果您的应用程序有许多这样的文件,把它们放在一个单独的目录中,按惯例命名为 static。

upload 表示当您部署应用程序时,什么必须上传到云端;例如,如果它包含 images/(*.ico|*.gif|*.jpg),它将把本地 images 目录内所有这些类型的文件上传到 AppEngine 服务器。

正如我们将看到的,大多数 GAE 应用程序也使用模板文件,这些文件可以存储在根应用程序地图中,或在一个特殊的目录 tmpl 中。

因此,一个 GAE 应用程序的一般结构可能是:

yourapp\ 		// map of the GAE application
		app.yaml // configuration file
		yourpackage\ // map containing the source files
			package1.go
			…
		tmpl\ // map containing template files
			root.html
			update.html
			…
		static\ // map containing static files
			yourapp.ico
			…

与 demo 一样,在控制台窗口中进入包含 helloapp 的映像,并发出如下命令:dev_appserver.py helloapp

或者你可以通过任何一个映像的 console 窗口并且唤醒:

dev_appserver.py /path_to_map_helloapp/helloapp

在这两种情况下,网络服务器现在都在运行,并监听 8080 端口的请求。通过在你的网络浏览器中访问以下 URL 来测试该应用程序:http://localhost:8080/

你应该看到: Hello, world!

在服务器控制台,出现以下文字:

$ dev_appserver.py helloapp
INFO 2011-10-31 08:54:29,021 appengine_rpc.py:159] Server: appengine.google.com
INFO 2011-10-31 08:54:29,025 appcfg.py:463] Checking for updates to the SDK.
INFO 2011-10-31 08:54:29,316 appcfg.py:481] The SDK is up to date.
WARNING 2011-10-31 08:54:29,316 datastore_file_stub.py:512] Could not read datastore
data from /tmp/dev_appserver.datastore
INFO 2011-10-31 08:54:29,317 rdbms_sqlite.py:58] Connecting to SQLite database ‘’
with file ‘/tmp/dev_appserver.rdbms’
INFO 2011-10-31 08:54:29,638 dev_appserver_multiprocess.py:637] Running application
helloworld on port 8080: http://localhost:8080
		<-(A)
INFO 2011-10-31 08:56:13,148 __init__.py:365] building _go_app
		<-(B)
INFO 2011-10-31 08:56:15,073 __init__.py:351] running _go_app
INFO 2011-10-31 08:56:15,188 dev_appserver.py:4143] “GET / HTTP/1.1” 200 -
		<-(C)

在 (A) 处服务器准备好了,在 (B) 处服务器编译并运行 Go 程序,在 (C) 处我们的应用程序的请求进来了,此时 HTML 输出页面被提供到服务器上。

当服务器被终止或尚未启动,而客户端请求网址 http://localhost:8080/,浏览器在FireFox 中会打印出这样的信息:

Unable to connect Firefox can’t establish a connection to the server at localhost:8080.

20.4.3 迭代开发

开发应用的服务器会观察你的文件中的变化,当你更新你的源代码时(编辑+保存),它重新编译它们并重新启动你的本地应用;不需要重新启动 dev_appserver.py

现在试试:让 Web 服务器运行,然后编辑 helloworld2.go,将 "Hello, world!" 改为其他内容。重新加载 http://localhost:8080/,就可以看到变化了:这和编写 Rails 或 Django 应用程序一样,都是动态运行的。

要关闭 Web 服务器,确保终端窗口处于活动状态,然后按 Ctrl+C(或适当的用于控制台的 "break "键):

INFO 2011-10-31 08:56:21,420 dev_appserver.py:4143] “GET / HTTP/1.1” 200 -
INFO 2011-10-31 08:57:59,836 __init__.py:365] building _go_app <-(D)
INFO 2011-10-31 08:58:00,365 __init__.py:351] running _go_app
INFO 2011-10-31 08:58:00,480 dev_appserver.py:4143] “GET / HTTP/1.1” 200 -
^CINFO 2011-10-31 08:58:32,769 dev_appserver_main.py:665] Server interrupted by user,
terminating <-(E)

这可以从上面第一个列表之后的服务器控制台输出中看到:在 (D) 处,apperver 看到 Go 的源代码被改变了,并重新编译;在 (E) 处,服务器被终止了。

20.4.4. 与 GoClipse IDE 的集成

a) 窗口/首选项/Go:

将所有内容指向 GAE 的 Go 根目录

b) 运行/外部工具/外部工具配置/选择程序:

​ 制作新的配置:点击 New 按钮。 ​ 名称:GAE ​ 位置:/home/user/google_appengine/dev_appserver.py ​ 工作目录:/home/user/workspace/bedilly/src/pkg/helloapp ​ 参数: home/user/workspace/bedilly/src/pkg/helloapp ​ 应用/运行

通过配置一个外部工具,部署你的应用程序也很容易:http://code.google.com/p/goclipse/wiki/DeployingToGoogleAppEngineFromEclipse

链接

上一节:

下一节:

20.3 节
Listing 20.2 helloworld2_version1.go
第 15 章
目录
安装 Go App Engine SDK
使用用户服务和探索其 API