在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
GO语言的进阶之路-go的程序结构以及包简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.编辑,编译和运行
A,编辑
Go程序使用UTF-8编码的纯Unicode文本编写。大部分现代编译器都能够自动处理编码,并且某些最流行的编辑器还支持Go语言的语法高亮和自动缩进。如果你用的编辑器不支持Go语言,可以在Go语言官网的搜索框中输入编辑器的名字,看看是否有适合的插件可用。为了编辑方便,所有的Go语言关键字和操作符都使用ASCII编码字符,但是Go语言中标识符可以是任一Unicode编码字符后跟若干Unicode字符或数字,这样Go语言开发可以在代码中只有的使用它们的母语。
B,编译 说道编译,我们不得不了解2个命令,一个是"go build",另外一个是“go install”。 前者大家应该都很熟悉,因为我在上一篇(http://www.cnblogs.com/yinzhengjie/p/6482675.html)关于GO的博客中用"go build"命令编译不同的版本,但是在这里我们还是要演示一下go build的花式用法。 1 package main 2 3 import ( 4 "os" 5 "fmt" 6 ) 7 8 func main() { 9 var s,sep string 10 for i := 1; i < len(os.Args);i++{ 11 s += sep + os.Args[i] 12 sep = " " 13 } 14 fmt.Println(s) 15 } 1.go build后加参数 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 在命令行中执行go build + [go文件],那么久会生成一个可执行的二进制文件, 9 ''' 10 [root@yinzhengjie day2]# ll 11 total 4 12 -rw-r--r-- 1 root root 165 Jun 13 14:45 myecho.go 13 [root@yinzhengjie day2]# 14 [root@yinzhengjie day2]# go build myecho.go 15 [root@yinzhengjie day2]# ll 16 total 1520 17 -rwxr-xr-x 1 root root 1551621 Jun 13 15:11 myecho 18 -rw-r--r-- 1 root root 165 Jun 13 14:45 myecho.go 19 [root@yinzhengjie day2]# 2.go build后不加参数 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 在命令行中执行:go build命令,如果不加任何参数的话,它就会把当前目录下的所有go文件统一进行编译,如果这些文件编译没有出错的话, 9 成功编译后会生成一个以当前目录问名字的二进制文件。 10 ''' 11 12 [root@yinzhengjie day2]# ll 13 total 4 14 -rw-r--r-- 1 root root 165 Jun 13 14:45 myecho.go 15 [root@yinzhengjie day2]# 16 [root@yinzhengjie day2]# go build 17 [root@yinzhengjie day2]# 18 [root@yinzhengjie day2]# ll 19 total 1520 20 -rwxr-xr-x 1 root root 1551621 Jun 13 15:15 day2 21 -rw-r--r-- 1 root root 165 Jun 13 14:45 myecho.go 22 [root@yinzhengjie day2]# ./day2 111 222 333 23 111 222 333 24 [root@yinzhengjie day2]# 要注意的是,以上编译出来的文件,我们可以将其放在"$GOPATH/bin目录下"这样我们就可以在任何目录下执行编译出来的那个文件名字啦,前提是你的"$PATH"设置的是OK的! 当你会用"go build"命令的话,其实"go install"就更简单了。但是首先你要知道为什么会用go install这个命令!我们在编译一个文件的时候用“go build”命令是很好使的,没有必要用“go install”这个命令,但是一个目录下有好多过go文件的话,我们应该咋办呢?这个时候用"go install"的优势就体现出来了。它会把当前目录(我们可以理解这个目录其实就是一个package)所有的go文件都进行编译。他和"go build”唯一明显的区别就是:"多做了一个mv的操作,也就是说用'go build'命令编译出来的代码最终会在当前目录下生成一个文件,而'go install'命令就会将生成的这个文件移动到$GOPATH/bin目录下。"这样方便你在任何路径下动都可以使用你编译好的文件程序。 不得不说的是,在用"go install"这个命令时,你不得不对"package"进行了解,在命令行敲击这个命令的时候你需要检查以你的环境。如果环境配置正确的话,是不会报错的! 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 'go install'和"go build”唯一明显的区别就是:"多做了一个mv的操作,也就是说用'go build'命令编译出来的代码最终会在当前目录下生成 9 一个文件,而'go install'命令就会将生成的这个文件移动到$GOPATH/bin目录下。这样方便你在任何路径下动都可以使用你编译好的文件程序。 10 ''' 11 12 [root@yinzhengjie day2]# go env #查看go的环境变量 13 GOARCH="amd64" 14 GOBIN="/yinzhengjie/go_file/bin" #配置的bin目录 15 GOEXE="" 16 GOHOSTARCH="amd64" 17 GOHOSTOS="linux" 18 GOOS="linux" 19 GOPATH="/yinzhengjie/go_file" #项目存放目录 20 GORACE="" 21 GOROOT="/yinzhengjie/golang/local/go" #go程序安装目录 22 GOTOOLDIR="/yinzhengjie/golang/local/go/pkg/tool/linux_amd64" 23 GCCGO="gccgo" 24 CC="gcc" 25 GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0" 26 CXX="g++" 27 CGO_ENABLED="1" 28 PKG_CONFIG="pkg-config" 29 CGO_CFLAGS="-g -O2" 30 CGO_CPPFLAGS="" 31 CGO_CXXFLAGS="-g -O2" 32 CGO_FFLAGS="-g -O2" 33 CGO_LDFLAGS="-g -O2" 34 [root@yinzhengjie day2]# 注意,以上是查看go环境,但是这些参数具体在哪里配置呢?有很多定义系统变量的文件都可以,我用的是"~/.bash_profile"这个文件来进行编辑的,具体配置我们只需要在这个文件中添加以下几行就OK啦: 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 export GOROOT=/yinzhengjie/golang/local/go 8 export GOPATH=/yinzhengjie/go_file 9 export PATH=$GOROOT/bin:$GOPATH/bin:$PATH 10 export GOBIN=$GOPATH/bin 其实,要想使用“go install”命令的话,我们需要手动指定一个在$GOPATH目录下手动创建一个"src"目录。然后在这个src目录下创建你的子目录,也可以说是不同的项目,当你在这个不同的项目中使用“go install”命令时,会在$GOPATH的bin目录下自动生成一个文件,以便你全局调用这个程序文件。 1.go install后不跟参数用法 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 [root@yinzhengjie day2]# ll 8 total 4 9 -rw-r--r-- 1 root root 165 Jun 13 17:25 myecho.go 10 [root@yinzhengjie day2]# 11 [root@yinzhengjie day2]# go install 12 [root@yinzhengjie day2]# 13 [root@yinzhengjie day2]# ls 14 myecho.go 15 [root@yinzhengjie day2]# day2 111 222 333 16 111 222 333 17 [root@yinzhengjie day2]# 2.go install跟参数用法 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 [root@yinzhengjie day2]# ll 8 total 4 9 -rw-r--r-- 1 root root 165 Jun 13 17:25 myecho.go 10 [root@yinzhengjie day2]# 11 [root@yinzhengjie day2]# go install myecho.go 12 [root@yinzhengjie day2]# 13 [root@yinzhengjie day2]# myecho 666 777 888 14 666 777 888 15 [root@yinzhengjie day2]# C.运行 相比大家玩过shell的人应该都是如果想要一个脚本直接在服务器上跑起来,需要给他家执行权限,但是没有执行权限的话也要运行这个脚本,我们可以用"sh + [脚本名]"照样是可以运行的。 那么在go程序中要使得go程序跑起来我们应该如何操作呢?其实我们有两种方法,一种就是类似于shell那样,不给这个go文件添加执行权限,用"go run或者gonow"命令来运行这个脚本;还有一种方法就是用“go build”命令将这个go文件编译成一个二进制可执行文件,然后在命令行中直接运行即可。 1.go run 用法展示 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 [root@yinzhengjie day2]# ll 8 total 4 9 -rw-r--r-- 1 root root 165 Jun 13 17:25 myecho.go 10 [root@yinzhengjie day2]# go run myecho.go 111 222 333 11 111 222 333 12 [root@yinzhengjie day2]# 2.go build用法展示 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 [root@yinzhengjie day2]# ll 8 total 4 9 -rw-r--r-- 1 root root 165 Jun 13 17:25 myecho.go 10 [root@yinzhengjie day2]# go build myecho.go 11 [root@yinzhengjie day2]# 12 [root@yinzhengjie day2]# ll 13 total 1520 14 -rwxr-xr-x 1 root root 1551621 Jun 13 17:38 myecho 15 -rw-r--r-- 1 root root 165 Jun 13 17:25 myecho.go 16 [root@yinzhengjie day2]# ./myecho 333 555 888 17 333 555 888 18 [root@yinzhengjie day2]#
二.package那些事 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 1.做一个项目一般不会用一个文件就搞定了,可能需要多个文件才能搞定,这个时候我们就需要引入一个概念,即package, 9 这个包里面可以存放多个go文件。 10 2.一个package只能有一个main函数; 11 3.同一个目录下的go文件只能是一个package(换句话说,同一个目录下go文件中的package后面的关键字必须一样。); 12 4.同一个package下的目录可以共享变量;同一个package下的目录可以共享函数; 13 5.两种package,一种是库package,一种是二进制package.二进制package使用 main 来表示,库package的名字跟go文件所 14 在的目录名一样. 15 16 ''' 1.同个目录下引用其他包的变量 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 package的一个好处就是将你的代码按照文件进行处置,不同文件完成不同的事情, 9 ''' 10 11 ''' 12 [root@yinzhengjie myecho]# ll 13 total 8 14 -rw-r--r-- 1 root root 184 Jun 14 15:24 myecho.go 15 -rw-r--r-- 1 root root 48 Jun 14 15:24 name.go 16 [root@yinzhengjie myecho]# 17 [root@yinzhengjie myecho]# more name.go 18 package main 19 20 var name string = "yinzhengjie" 21 [root@yinzhengjie myecho]# 22 [root@yinzhengjie myecho]# more myecho.go 23 package main 24 25 import ( 26 "os" 27 "fmt" 28 ) 29 30 func main() { 31 var s,sep string 32 for i := 1; i < len(os.Args);i++{ 33 s += sep + os.Args[i] 34 sep = " " 35 } 36 fmt.Println(s) 37 fmt.Println(name) #虽然在当前文件中没有定义name变量,照样可以用! 38 } 39 40 [root@yinzhengjie myecho]# 41 [root@yinzhengjie myecho]# pwd 42 /yinzhengjie/go_file/src/day2/myecho 43 [root@yinzhengjie myecho]# 44 [root@yinzhengjie myecho]# go install 45 [root@yinzhengjie myecho]# 46 [root@yinzhengjie myecho]# myecho 666666 47 666666 48 yinzhengjie #这个是字符串。 49 [root@yinzhengjie myecho]# 50 51 ''' 2.引入自定义的package案例展示 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 [root@yinzhengjie golib]# pwd //模拟创建一个第三方包为"golib"包 9 /yinzhengjie/go_file/src/day1/golib 10 [root@yinzhengjie golib]# 11 [root@yinzhengjie golib]# ll 12 total 4 13 -rw-r--r-- 1 root root 59 Jun 15 09:48 math.go 14 [root@yinzhengjie golib]# 15 [root@yinzhengjie golib]# more math.go 16 package golib //这个目录下的所有package关键字后面必须都跟"golib"参数。 17 18 func Add(a int,b int) int { 19 return a + b 20 } 21 [root@yinzhengjie golib]# 22 [root@yinzhengjie testlib]# pwd 23 /yinzhengjie/go_file/src/day2/testlib 24 [root@yinzhengjie testlib]# 25 [root@yinzhengjie testlib]# ll 26 total 4 27 -rw-r--r-- 1 root root 94 Jun 15 09:46 import_package.go 28 [root@yinzhengjie testlib]# 29 [root@yinzhengjie testlib]# more import_package.go //创建一个脚本用于测试导入第三方库。 30 package main 31 import ( 32 "fmt" 33 "day1/golib" //需要写“src”目录下的绝对路径,导入"golib"的package. 34 ) 35 36 func main(){ 37 fmt.Println(golib.Add(100,200)) 38 } 39 [root@yinzhengjie testlib]# 40 [root@yinzhengjie testlib]# go install 41 [root@yinzhengjie testlib]# testlib 42 300 43 [root@yinzhengjie testlib] 44 45 ''' 3.查询package说明文档 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 也许你知道通过官网查询第三方包说明文档,比如要查看os,就在浏览器的地址栏输入:"https://godoc.org/os"这个 9 网址你就能看到相应的说明了,但是如果这个package是你自定义的,你们公司要用你的 程序,你需要写一个说明文档供应 10 大家查看。这个时候我们就用到了一个比较神奇的工具,“godoc”工具可以启动服务器的一个web端口。 11 ''' 12 13 ''' 14 [root@yinzhengjie golib]# pwd 15 /yinzhengjie/go_file/src/day1/golib 16 [root@yinzhengjie golib]# 17 [root@yinzhengjie golib]# 18 [root@yinzhengjie golib]# ll 19 total 4 20 -rw-r--r-- 1 root root 94 Jun 15 10:07 math.go 21 [root@yinzhengjie golib]# 22 [root@yinzhengjie golib]# more math.go 23 package golib 24 25 26 //ADD return a + b by yinzhengjie 27 func Add(a int,b int) int { 28 return a + b 29 } 30 [root@yinzhengjie golib]# 31 [root@yinzhengjie ~]# godoc -http=:8000 & #表示启动本地的服务器8000端口供大家查看你自定义的package! 32 [1] 29084 33 [root@yinzhengjie ~]# 34 [root@yinzhengjie ~]# ip a | grep eth | grep inet | awk '{print $2}' | awk -F "/" '{print $1}' #查看当前服务器的IP,只需要在web上输入"IP:端口"即可 35 172.16.3.211 36 [root@yinzhengjie ~]# 37 ''' 下面我们就需要在web端输入相应的地址即可:“http://172.16.3.211:8000/doc/” a>.点击package b>.找到了你自定义的package,查看相关信息即可。 c>.点击你自定义的包名,查看其内容说明即可。 以上的操作是告诉我们如何在本地实现如何让大家访问,那么如何把你的代码推送到github上去呢?可以参考我的笔记:http://www.cnblogs.com/yinzhengjie/p/7017036.html。如果你需要用到第三方模块在别人的github账号的仓库里,那么我们可以先把他们的环境项目下载下来,然后在引用他们的代码。配置起来也特别简单,就两条命令的事情。 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 [root@yinzhengjie testlib]# ll $GOPATH 9 total 8 10 drwxr-xr-x 2 root root 4096 Jun 15 14:10 bin 11 drwxr-xr-x 5 root root 4096 Jun 15 12:16 src 12 [root@yinzhengjie testlib]# 13 [root@yinzhengjie testlib]# go get github.com/yinzhengjie/golib #将github上的项目下载到本地的GOPATH环境变量中, 14 [root@yinzhengjie testlib]# 15 [root@yinzhengjie testlib]# ll $GOPATH 16 total 12 17 drwxr-xr-x 2 root root 4096 Jun 15 14:10 bin 18 drwxr-xr-x 3 root root 4096 Jun 15 14:16 pkg 19 drwxr-xr-x 5 root root 4096 Jun 15 12:16 src 20 [root@yinzhengjie testlib]# 21 [root@yinzhengjie src]# ll 22 total 12 23 drwxr-xr-x 4 root root 4096 Jun 15 09:40 day1 24 drwxr-xr-x 3 root root 4096 Jun 15 09:43 day2 25 drwxr-xr-x 3 root root 4096 Jun 15 12:16 github.com #多出来的项目 26 [root@yinzhengjie src]# pwd 27 /yinzhengjie/go_file/src 28 [root@yinzhengjie src]# 29 [root@yinzhengjie testlib]# more import_package.go 30 package main 31 import ( 32 "fmt" 33 "github.com/yinzhengjie/golib" //我们可以导入下载后的第三方库 34 ) 35 36 func main(){ 37 fmt.Println(golib.Add(100,200)) 38 } 39 [root@yinzhengjie testlib]# 40 '''
好了,经过上面的案例,大家也许已经看出来Golang关于package的特点,我总结如下: A.从package的角度来说: 1>.首先,该package必须是在GOPATH路径下; 2>.一个package可用存在多个“*.go”文件,但是每个“*.go”文件的开头第一行必须是其package + 名称(你可以理解是代码存放的目录名称)。 3>.一个package可用存在多个“*.go”文件,但是每个“*.go”文件的开头第一行必须是其package + mian 。但是要注意的是在这个目录下的所有“*.go”文件中只能存在一个main函数。
B.从调用的角度来说: 1>.调用时,需要从GOPATH路径中的src目录(你可以理解成是库的根目录)下的第一个目录开始写,直到写到包名的路径为止。 2>.调用的时候,你的代码可以在操作系统的任何路径下调用。
扩展小知识: 在一个新的服务器上GOPATH目录下新建了一个src目录,但是初次从github下载一个模块的时候,会在src目录下生成一个pkg目录,这个目录是干嘛用的呢? 答案:pkg是编译的中间产物。编译分为编译->链接的过程,“pkg”里面放的是编译的产物,二进制是链接的产物。如果干掉这个“pkg”目录后还会自动生成,具体缓存的作用。具体的信息可以问问我的大师兄和二师兄。
三.代码风格 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:[email protected] 6 7 ''' 8 1.所有的代码只有一种,gofmt的风格; 9 2.gofmt 不是任何人的风格,但所有人都喜欢 gofmt 的风格; 10 3.使用 `gofmt -w xx.go` 来格式化代码; 11 '''
四.命令行参数 1 [root@yinzhengjie day2]# pwd 2 /yinzhengjie/go_file/src/day2 3 [root@yinzhengjie day2]# 4 [root@yinzhengjie day2]# ll 5 total 12 6 -rw-r--r-- 1 root root 178 Jun 15 15:41 args.go 7 -rw-r--r-- 1 root root 184 Jun 14 15:21 myecho.go 8 -rw-r--r-- 1 root root 48 Jun 14 15:21 name.go 9 [root@yinzhengjie day2]# 10 [root@yinzhengjie day2]# go run args.go 111 222 333 11 [/tmp/go-build716596169/command-line-arguments/_obj/exe/args 111 222 333] 12 first 111 13 second 222 14 third 333 15 [root@yinzhengjie day2]# 16 [root@yinzhengjie day2]# go build args.go 17 [root@yinzhengjie day2]# 18 [root@yinzhengjie day2]# ./args 111 222 333 19 [./args 111 222 333] 20 first 111 21 second 222 22 third 333 23 [root@yinzhengjie day2]# 24 [root@yinzhengjie day2]# 25 [root@yinzhengjie day2]# more args.go 26 package main 27 28 import ( 29 "fmt" 30 |
请发表评论