Selaa lähdekoodia

第九章第五至11节翻译内容

Spawnris 11 vuotta sitten
vanhempi
commit
a4fff976c8
7 muutettua tiedostoa jossa 450 lisäystä ja 0 poistoa
  1. BIN
      eBook/09.10.md
  2. 62 0
      eBook/09.11.md
  3. 139 0
      eBook/09.5.md
  4. 34 0
      eBook/09.6.md
  5. 37 0
      eBook/09.7.md
  6. 124 0
      eBook/09.8.md
  7. 54 0
      eBook/09.9.md

BIN
eBook/09.10.md


+ 62 - 0
eBook/09.11.md

@@ -0,0 +1,62 @@
+#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

+ 139 - 0
eBook/09.5.md

@@ -0,0 +1,139 @@
+#B 自定义和外部包的使用,编译,测试,文档和安装
+#9.5 自定义包和可见性
+
+包是Go语言中代码组成和代码编译的主要方式。很多关于它们的基本信息已经在4.2章节中给出,最引人注目的便是可见性。现在我们来看看具体如何来使用自己写的包。在下一节,我们将回顾一些标准库中的包,自定义的包和标准库以外的包。
+
+当写自己包的时候,要使用短小的不含有_(下划线)的小写单词来为文件命名。这里有个简单例子来说明包是如何相互调用以及可见性是如何实现的。
+
+当前目录下(examples/chapter9)有一个名为package_test.go的程序, 它使用了自定义包pack1中pack1.go的代码。这段程序(联通编译链接生成的pack1.a)存放在当前目录下一个名为pack1的文件夹下。所以链接器将包的对象和主程序对象链接在一起。
+
+示例 9.4 [pack1.go](exmaples/chapter_9/pack1.go)
+
+    package pack1
+    var Pack1Int int = 42
+    var PackFloat = 3.14
+    
+    func ReturnStr() string {
+    	return "Hello main!"
+    }
+    
+它包含了一个整型变量PackInt和一个返回字符串的函数ReturnStr。这段程序在运行时不做任何的事情,因为它不包含有一个main函数。
+
+在主程序pack_test.go中这个包通过声明的方式被导入
+
+	 import “./pack1/pack1”


import的一般格式如下:
+
	import “包的路径或url地址“ 像 import "github.com/org1/pack1”
+
+路径是指当前目录的相对路径。
+
+示例 9.5 [package_test.go](exmaples/chapter_9/package_test.go)
+	
+	package main
+	import (
+		"fmt"
+		"./pack1/pack1"
+	)
+		
+	func main() {
+		var test1 string
+		test1 = pack1.ReturnStr()
+		fmt.Printf("ReturnStr from package1: %s\n", test1)
+		fmt.Printf(“Integer from package1: %d\n”, pack1.Pack1Int)
		// fmt.Printf(“Float from package1: %f\n”, pack1.pack1Float)
+
		
+
输出结果:
+
	ReturnStr from package1: Hello main! 
	Integer from package1: 42
+
	
+
如果包pack1和我们的程序在统同一路径下,我们可以通过"import ./pack1"这样的方式来引入,但这不被视为一个好的方法。
+
fmt.Printf(“Float from package1: %f\n”, pack1.pack1Float)这行代码试图访问一个未引用的变量或者函数,甚至没有编译。将会返回一个错误:
+
	cannot refer to unexported name pack1.pack1Float
+
	
+主程序利用的包必须在主程序编写之前被编译。主程序中每个pack1项目都要通过包名来使用使用:pack1.Item。具体使用方法请参见示例4.6和4.7。		
+	
+因此,按照惯例子目录和包之间有着密切的联系:为了区分不同包存放在不同的目录,每个包(所有属于这个包中的go文件)都存放在和包名相同的子目录下。
+
+	Import with . : import . “./pack1”
+	
+当使用.来做为包的别名时,你可以不通过包名来使用其中的项目。例如:test := ReturnStr()。
+
+在当前的命名空间导入pack1包,一般是为了具有更好的测试效果。
+
+	Import with _ : import _ “./pack1/pack1”
+
+pack1包只导入其副作用,只执行了它的init函数并初始化了其中的全局变量
+
+导入外部安装包:  
+如果你要在你的应用中使用一个或多个外部包,首先你必须使用go install(参见9.7章节)在你的本地机器上安装它们。
+
+假设你想使用http://codesite.ext/author/goExample/goex这种托管在googlecode,  github,launchpad等代码网站上的包。
+
+你可以通过如下命令安装  
+
+	go install codesite.ext/author/goExample/goex
+
+将一个名为codesite.ext/author/goExample/goex的map安装在$GOROOT/src/目录下。
+
+通过以下方式,一次性安装,并导入到你的代码中:
+
+	import goex “codesite.ext/author/goExample/goex”
+	
+因此你项目的路径将成为导入包的网络地址
+
+在http://golang.org/cmd/goinstall/的go install文档中列出了一些广泛被使用的托管在网络代码仓库的包的导入路径
+
+包的初始化:  
+程序的执行开始于导入包,初始化main包然后调用main函数。
+
+一个没有导入的包将通过分配初始值给所有的包级变量和调用源码中定义的包级init函数来初始化。一个包可能有多个init函数甚至在一个源码文件中。它们的执行是无序的。这是最好的例子来测定包的值是否只依赖于相同包下的其他值或者函数。
+
+init函数是不能被调用的。
+
+导入的包在包自身初始化前被初始化,而一个包在程序执行中只能初始化一次。
+
+编译并安装一个包(参见9.7章节):
+
+在Linux/OSX下可以用类似4.3章节的Makefile脚本做到这一点:
+
+	include $(GOROOT)/src/Make.inc
	TARG=pack1
	GOFILES=\
	 	pack1.go\
	 	pack1b.go\
	include $(GOROOT)/src/Make.pkg
+

确保的它可执行性通过 chmod 777 ./Makefile。
+
+内置声明了自动检测机器体系结构和使用正确的编译器和链接器的功能。
+
+然后终端执行make或gomake:都会生成一个包含静态库pack1.a的_obj目录。
+
+go install(参见9.7章节,从Go1的首选方式)同样复制pack1.a到本地的$GOROOT/pkg的目录中一个以操作系统为名的子目录下。像 import "pack1"代替imort "path to pack1",这样只通过名字就可以将包在程序中导入。
+
+如果不可取或不被允许,通过6/8g使用-I选项来编译:
+	
+	6g—I map_pack1 package_test.go # where map_pack1 is the map which contains pack1.a
(I选项让编译器查找选项后的目录下是否包含这个包)
+
使用6/8l的-L选项链接:
+
	6l—L map_pack1 package_test.6
+
+当第13章我们遇到使用测试工具进行测试的时候我们将重新回到自己的包的制作和编译这个话题。
+
+练习:
+
+问题9.1:
+
+(a)一个包能分成多个源文件么?
+
+(b)一个源文件是否能包含多个包?
+
+练习 9.3:
+创建一个程序main_greetings.go能够和用户说"Good Day"或者"Good Night"。不同的问候应该放到greetings包中。
+
+在同一个包中创建一个ISAM函数返回一个布尔值用来判断当前时间是AM还是PM,同样创建IsAfternoon和IsEvening函数。
+
+使用main_greetings作出合适的问候。
+(提示:使用time包)
+
+练习	9.4:创建一个程序main_oddven.go判断前100个整数是不是偶数,包内同时包含测试的功能。
+
+练习 9.6:使用6.6章节的斐波那契程序
+
+(1)将斐波那契功能放入自己的fibo包中并通过主程序调用它,存储最后输入的值在函数的全局变量。
+
+(2)扩展fibo包将通过调用斐波那契的时候,操作也作为一个参数。实验"+"和“*” 
+
+main_fibo.go / fibonacci.go
+
+

+ 34 - 0
eBook/09.6.md

@@ -0,0 +1,34 @@
+#	9.6 为你的自定义包使用godoc
+godoc工具(3.6章节)在显示自定义包中的注释也有很好的效果:注释必须以//开始并无空行放在声明(包,类型,函数)前。godoc会为每个文件生成一系列的网页。
+
+例如:
+
+-在do_examples目录下我们有11.7章节中的用来排序的go文件,文件中有一些注释(文件需要未编译)
+
+-命令行下进入目录下并输入命令:
+	
+	godoc -http =:6060 -paht="."
+
+(.是指当前目录,-path参数可以是/path/to/my/package1这样的形式指出package1在你源码中的位置或接受用冒号形式分隔的路径,无根目录的路径为相对于当前目录的相对路径)
+
+-在浏览器打开地址 http://localhost:6060
+
+然后你会看到本地的godoc页面(参见3.6章节)从左到右一次显示出目录中的包
+doc_example:
+
+doc_example | Packages | Commands | Specification
+
+下面是链接到源码和所有对象时有序概述(所以是很好的浏览和查找源代码的方式),连同文件/评论。
+
+sort包
+
+func Float64sAreSorted 	
+
+type IntArray

func IntsAreSortedfunc IsSortedfunc Sort 
+
func (IntArray) Len

func SortFloat64s 
+
func (IntArray) Less

func SortInts 

func (IntArray) Swap

func SortStrings type Interface

func StringsAreSorted type StringArray

type Float64Array func (StringArray) Len

func (Float64Array) Len 
+
func (StringArray) Less

func (Float64Array) Less 
+
func (StringArray) Swap
+
func (Float64Array) Swap Other packages

import “doc_example”
使用通用的接口排序:
+
Package files  
sort.go  
func Float64sAreSorted[Top]  
func Float64sAreSorted(a []float64) bool  
func IntsAreSorted[Top]  
func IntsAreSorted(a []int) bool  
func IsSorted[Top]  
func IsSorted(data Interface) bool  
Test if data is sorted  
func Sort[Top]  
func Sort(data Interface)  
General sort function  
func SortInts[Top]  
func SortInts(a []int)  
Convenience wrappers for common cases  
type IntArray[Top]  
Convenience types for common cases: IntArray  
type IntArray []int  
+
如果你在一个团队中工作,并在源代码树被存储在网络硬盘上,就可以使用godoc给所有团队成员连续文档的支持。通过设置sync_minutes=n,你甚至可以让它自动更新您的文档每n分钟!

+ 37 - 0
eBook/09.7.md

@@ -0,0 +1,37 @@
+# 9.7使用go install安装自定义包
+
+go install是Go中自动包安装工具:如需要将包安装到本地它会从远端仓库下载包:检出,编译,安装一气呵成。
+
+在包安装前的先决条件是要自动处理包自身依赖关系的安装。被依赖的包也会安装到子目录下,但是没有文档和示例:可以到网上浏览。
+
+被安装包的列表可以在$GORROT/goinstall.log找到。
+
+go install使用了GOPATH变量(参见2.2章节)。
+
+远端包(参见9.5章节):
+
+假设我们要安装一个有趣的包tideland(它包含了许多帮助示例,参见http://code.google.com/p/tideland-cgl)。
+
+因为我们需要创建目录在Go安装目录下,所以我们需要使用root或者su的身份执行命令。
+
+确保Go环境变量已经设置在root用户下的./bashrc文件中。
+
+使用命令安装:go install tideland-cgl.googlecode.com/hg
+
+可执行文件hg.a将被放到$GOROOT/pkg/linux_amd64/tideland-cgl.googlecode.com目录下,源码文件被放置在$GOROOT/src/tideland-cgl.googlecode.com/hg目录下,同样有个hg.a放置在_obj的子目录下。
+
+现在就可以在go代码中使用这个包中的功能了,例如使用报名cgl导入:
+	
+	import cgl "tideland-cgl.googlecode.com/hg"
+	
+从Go1起go install安装Google Code的导入路径形式是:"code.google.com/p/tideland-cgl"
+
+升级到新的版本:
+
+更新到新版本的Go之后本地安装包的二进制文件将全被删除。当调用install-a工具将通过读取$GOROOT/goinstall.log重新安装以前的安装包。如果你想更新,重编译,重安装所有的go安装包可以使用:go install -a -u -clean 或者 go install -a -u -nuke
+
+go的版本发布的很频繁,所以需要注意发布版本和包的兼容性。go1之后都是自己编译自己了。
+
+go install同样可以使用go install编译链接并安装本地自己的包:参见9.8.2章节。
+
+更多信息可以在http://golang.org/cmd/go和http://golang.org/cmd/goinstall找到。

+ 124 - 0
eBook/09.8.md

@@ -0,0 +1,124 @@
+#9.8 自定义包:目录结构,go install和go test
+
+为了示范,我们创建了一个名为uc的简单包,它含有一个UpperCase函数将字符串的所有字母转换为大写。当然这并不值得创建一个自己包,同样的功能已被包含在"strings"包里,但是同样的技术也可以应用在更复杂的包中。
+##9.8.1 自定义包的目录结构
+下面的结构给了你一个好的示范(uc代表通用包名, 名字为粗体的代表目录,斜体代表可执行文件):	
+	
+	/home/user/goprograms
		ucmain.go	(uc包主程序)
		Makefile (ucmain的2-makefile)
		ucmain
		
		src/uc	 (包含uc包的go源码)
			uc.go
		 	uc_test.go
		 	Makefile (包的1-makefile)
		 	uc.a
		 	_obj
				uc.a
			_test
				
					uc.a
		bin		 (包含最终的执行文件)
			 	ucmain	
		pkg/linux_amd64	
				uc.a	(包的目标文件)
+

将你的项目放在goprograms目录下(你可以创建一个环境变量GOPATH,参考2.2/3章节:在.profile和.bashrc文件中添加export GOPATH=/home/user/goprograms),而你的项目将作为src的子目录。uc包 中的功能在uc.go中实现。
+
+示例 9.6 [uc.go](exmaples/chapter_9/uc.go)
+	
+	package uc
+	import "strings"
+	
+	func UpperCase(str string) string {
+		return strings.ToUpper(str)
+	} 
+        
+包通常附带一个或多个测试文件,在这我们创建了一个uc_test.go文件,如9.8章节所述
+
+示例 9.7 [test.go](examples/chapter_9/uc.go)
+
+	package uc
+	import "testing"
+	
+	type ucTest struct { 
+		in, out string
+	}
+	
+	var ucTests = []ucTest {
+		ucTest{"abc", "ABC"},
+		ucTest{"cvo-az", "CVO-AZ"},
+		ucTest{"Antwerp", "ANTWERP"},
+	}
+	
+	func TestUC(t *testing.T) {
+		for _, ut := range ucTests {
+			uc := UpperCase(ut.in)
+			if uc != ut.out {
+				t.Errorf("UpperCase(%s) = %s, must be %s", ut.in, uc, 
+				ut.out)
+			}
+		}
+	}
+通过指令编译并安装包到本地:go install src/uc, 这会将uc.a复制到pkg/linux_amd64下面
+另外,使用make,通过以下内容创建一个包的Makefile(1)在src/uc目录下:
+	
+	include $GOROOT/src/Make.inc
+	
+	TARG=uc
+	GOFILES=\
+			uc.go\
+		
+	include $(GOROOT)/scr/Make.pkg
+在该目录下的命令行调用: gomake
+
+这将创建一个_obj目录并将包编译生成的存档uc.a放在该目录下
+
+这个包可以通过go test测试
+
+创建一个ud.a的测试文件在目录下,输出为PASS时测试通过
+
+在13.8章节我们将给出另外一个测试例子并进行深入研究
+
+备注:有可能你当前的用户不具有足够的资格使用go install(没有权限)。这种情况下,选择root用户su。确保Go环境变量和Go源码路径也设置给su,同样也适用你的普通用户(详见2.3章节)
+
+接下来我们创建主程序ucmain.go:
+
+示例 9.8 [ucmain.go](/examples/chapter_9/ucmain.go)
+
+	package main
+	import (
+		"fmt"
+		"./uc/uc"
+	)
+	
+	func main() {
+		str1 := "USING package uc"
+		fmt.Println(uc.UpperCase(str1))
+	}
+	
+然后在这个目录下输入go install
+
+另外复制uc.a到uc目录并创建一个Makefile(2)并写入文本:
+包含在$GOROOT/src/Make.inc
+
+	TARG=ucmain
+	GOFILES=\
+		ucmain.go\
+	
+	include $GOROOT/src/Make.cmd
+	
+执行gomake编译ucmain.go到ucmain目录
+
+运行./ucmain显示: USING package uc!
+
+## 9.8.2 本地安装包
+本地包在用户目录下:
+使用给出的目录结构,以下命令用来从源码安装本地包:
+	
+	go install /home/user/goprograms/src/uc # 编译安装uc
	cd /home/user/goprograms/uc
	go install ./uc 	# 编译安装uc(和之前的指令一样)
	cd ..
	go install .	# 编译安装ucmain
+
安装到$GOROOT下:
+
如果我们想安装的包在系统上的其他Go程序中被使用,它一定要安装到$GOROOT下。
+
这样做,在.profile和.bashrc中设置GOPATH=$GOROOT。然后执行go install uc将会:
+
+(1) 复制源代码到$GOROOT/src/pkg/linux_amd64/uc
+
+(2) 复制包存档到$GOROOT/PKG/LINUX_AMD64/uc
+
+uc包可以通过"import uc"在任何Go程序中被引用。
+
+
+## 9.8.3 依赖系统的代码
+
+不同操作系统上运行不同的程序是非常少见的:绝大多数情况下语言和标准库解决了大部分的可移植性问题。
+
+你有一个很好的理由去写平台平台特定的代码,例如汇编语言。这种情况下,按照下面的约定是合理的:
+
+	prog1.go
	prog1_linux.go
	prog1_darwin.go
	prog1_windows.go
+
prog1.go定义了不同操作系统通用的接口,并将系统特定的代码写到prog1_os.go中。
+

对于Go工具你可以指定:prog1_$GOOS.go or prog1_$GOARCH.go
+
或在平台Makefile中: prog1_$(GOOS).go\ or prog1_$(GOARCH).go\
+

示例 9.6: package strev
+
运用前面9.7章节所有技术使用strev包解决练习9.2。

+ 54 - 0
eBook/09.9.md

@@ -0,0 +1,54 @@
+#9.9 通过git打包和安装
+##9.9.1 安装到github   
+以上的方式对于本地包来说是可以的,但是我们如何打包代码到开发者圈子呢?那么我们需要一个云端的源码的版本控制系统,比如著名的git。
+
+在Linux和OS X的机器上git是默认安装的,在windows上你必须先自行安装,参见http://
help.github.com/win-set-up-git/
+
+这里将通过为9.8章节中的uc包创建一个git仓库作为演示
+
+进入到uc包目录下并创建一个git仓库在里面: git init .
+信息提示: Initialized empty git repository in .../uc
+
+每一个git项目都需要一个对包进行描述的README文件,所以打开你的文本编辑器(gedit,notepad,LiteIde)添加一些说明进去。
+
+然后添加所有文件到仓库:git add README uc.go uc_test.go Makefile
+标记为第一个版本:	git commit -m "initial rivision"
+
+现在必须去登录github网站: https://github.com
+
+也许你还不能登录,你可以去https://github.com/plans注册一个开源项目的免费帐号。输入正确的帐号密码和有效的邮箱地址并进一步创建用户。然后你将获得一个git命令的列表。本地仓库的操作的命令已经完成。一个优秀的系统http://help.github.com/在你遇到任何问题的时候将引导你。
+
+在云端创建一个新的uc仓库;发布的指令为(NNNN替代用户名):   
+	
+git remote add orign [email protected]:NNNN/uc.git  
+git push -u origin master
+	
+操作完成后检查github上的包页面: http://github.com/NNNN/uc
+
+##9.9.2 从github安装
+如果有人想你的远端项目到本地机器,打开终端并执行: go install github.com/NNNN/uc
+
+NNNN是你在github上的用户名
+
+复制  
+->uc.a包到目录$GOROOT/PKG/LINUX_AMD64/github.com  
+->源码到$GOROOT/src/pkg/github.com/NNNN/uc
+	
+这样现在这台机器上的其他Go应用程序也可以通过导入路径:"github.com/NNNN/uc"代替"./uc/uc"来使用。
+
+也可以将其缩写为: import uc "github.com/NNNN/uc"
+
+然修改Makefile: 将TARG=uc替换为TARG-github.com/NNNN/uc
+
+Gomake(和go install)将通过$GOROOT下的本地版本进行工作。
+
+网站和版本控制系统:其他的选择
+
+主要网站有(括号中为网站所使用的版本控制系统):
+
+*	bitbucket(hg)
+*	github(git)
+*	googlecode(hg/git/svn)
+*	launchpad(bzr)
+
+版本控制系统可以选择你熟悉的或者本地使用的代码版本控制。Go核心代码的仓库是使用Mercurial(hg)来控制的,所以它是一个最可能保证你可以得到开发者项目中最好的软件。Git也很出名,同样也适用。如果你从未使用过的版本控制,这些网站有一些很好的帮助并且你可以通过在谷歌搜索"{name} tutorial"name为你想要使用的版本控制系统得到许多很好的教程。