#9.11 在Go程序中使用外部库
(本节我们将创建一个web应用和它的Google App Engine版本,在第19和21章分别说明，当你阅读到这些章节时可以再回到这个例子。)

当开始一个新项目或增加新的功能到现有的项目，你可以通过在应用程序中使用已经存在的库来节省开发时间。为了做到这一点，你必须理解库的API（应用编程接口），那就是：库中有哪些方法可以调用，如何调用。你可能没有这个库的源代码，但作者肯定有记载的API以及详细介绍了如何使用它。

作为一个例子，我们将使用谷歌的API的urlshortener编写一个小程序：你可以尝试一下在http://goo.gl/输入一个像"http://www.destandaard.be"这样的URL，你会看到一个像"http://goo.gl/O9SUO"这样更短的URL返回，也就是说，在Twitter之类的服务中这是非常容易嵌入的。谷歌urlshortener服务的文档可以在"http://code.google. com/apis/urlshortener/"找到。 (第19章，我们将开发自己版本的urlshortener)。

谷歌将这项技术提供给其他开发者，作为API我们可以在我们自己的应用程序中调用（释放到指定的限制。他们也生成了一个Go语言客户端库使其变得更容易。

备注：谷歌让通过使用Google API Go客户端服务的开发者生活变得更简单，Go客户端程序自动生成于Google库的JSON描述。更多详情在http://code.google.com/p/google-api-go-client/。

下载并安装Go客户端库:
将通过go install实现。但是首先要验证环境变量中是否含有GOPATH变量，因为外部源码将被下载到$GOPATH/src目录下并被安装到$GOPATH/PKG/"machine_arch"/目录下。

我们将通过在终端调用以下命令来安装API:
	
go install google-api-go-client.google.com/hg/urlshortener/v1

go install将下载源码，编译并安装包

(在Linux Ubuntu下使用6g r60 9841安装是可以的,被安装文件被放在pkg/linux_amd64下)

使用urlshortener服务的web程序:
现在我们可以通过导入并赋予别名来使用已安装的包：import urlshortener "google-api-go-client.googlecode.com/hg/urlshortener/v1"

现在我们写一个web应用(参见第十五章4-8节)通过表单实现短地址和长地址的相互转换。我们将使用template包并写三个处理函数：root函数通过执行表单模板来展示表单。short函数将长地址转换为短地址，long函数逆向转换。

要调用urlshortener接口必须先通过http包中的默认客户端创建一个服务实例urlshortenerSvc：  
  	
  	urlshortenerSvc, _ := urlshortener.New(http.DefaultClient)

我们通过调用服务中的Url.Insert中的Do方法传入包含长地址的Url数据结构从而获取短地址：
	
	url, _ := urlshortenerSvc.Url.Insert(&urlshortener.Url{LongUrl: longUrl}).Do()
	
返回url的Id便是我们需要的短地址。

我们通过调用服务中的Url.Get中的Do方法传入包含短地址的Url数据结构从而获取长地址：
	
	url, error := urlshortenerSvc.Url.Get(shwortUrl).Do()
	
返回的长地址便是转换前的原始地址。

实例	9.9	[urlshortener.go](examples/chapter_9/urlshortener.go)

	package main
	import (
		 “fmt”
		 “net/http”
		 “text/template”
		
		rlshortener “google-api-go-client.googlecode.com/hg/urlshortener/v1”
	)
	func main() {
		 http.HandleFunc(“/”, root)
		 http.HandleFunc(“/short”, short)
		 http.HandleFunc(“/long”, long)
	
		http.ListenAndServe(“localhost:8080”, nil)
	}
	// the template used to show the forms and the results web page to the user
	var rootHtmlTmpl = template.Must(template.New(“rootHtml”).Parse(`
	<html><body>
	<h1>URL SHORTENER</h1>
	{{if .}}{{.}}<br /><br />{{end}}
	<form action=”/short” type=“POST”>
	Shorten this: <input type=“text” name=“longUrl” />
	<input type=“submit” value=“Give me the short URL” />
	</form>
	<br />
	<form action=”/long” type=“POST”>
	Expand this: http://goo.gl/<input type=“text” name=“shortUrl” />
	<input type=“submit” value=“Give me the long URL” />
	</form>
	</body></html>
	`))
	func root(w http.ResponseWriter, r *http.Request) {
		rootHtmlTmpl.Execute(w, nil)
	}
	func short(w http.ResponseWriter, r *http.Request) {
		 longUrl := r.FormValue(“longUrl”)
		 urlshortenerSvc, _ := urlshortener.New(http.DefaultClient)
		 url, _ := urlshortenerSvc.Url.Insert(&urlshortener.Url{LongUrl:
		 longUrl,}).Do()
		 rootHtmlTmpl.Execute(w, fmt.Sprintf(“Shortened version of %s is : %s”,
		 longUrl, url.Id))
	}


	func long(w http.ResponseWriter, r *http.Request) {
		 shortUrl := “http://goo.gl/” + r.FormValue(“shortUrl”)
		 urlshortenerSvc, _ := urlshortener.New(http.DefaultClient)
		 url, err := urlshortenerSvc.Url.Get(shortUrl).Do()
		 if err != nil {
			 fmt.Println(“error: %v”, err)
			 return
		
		 }
		 rootHtmlTmpl.Execute(w, fmt.Sprintf(“Longer version of %s is : %s”,
		 shortUrl, url.LongUrl))
	}

编译这段代码: 6g -I $GOPATH/pkg/linux_amd64 urlshortener.go

链接这段代码: 6l -L $GOPATH/pkg/linux_amd64 urlshortener.6

执行这段代码：./6.out

(确认是否有其他的应用运行在http://localhost:8080,如果有这步将失败)通过浏览http://localhost:8080/的页面来测试。

为了代码的简洁我们并没有检测返回的错误状态，但是在真实的生产环境的应用中一定要做检测。

将应用放入Google App Engine：

我们只需要在之前的代码中作出如下改变：

	package main -> package urlshort

	func main() -> func init()

创建一个和包同名的目录: urlshort

将以下两个安装目录复制到这个目录：

	google-api-go-client.googlecode.com/hg/urlshortener
	google-api-go-client.googlecode.com/hg/google-api

此外还要配置下配置文件app.yaml，内容如下：

	application: urlshort
	version: 0-1-test
	runtime: go
	api_version: 3
	handlers:
	- url: /.*
	script: _go_app

现在你可以去到你的项目目录并在终端运行：dev_appserver.py urlshort

在浏览器打开你的web应用：http://localhost:8080