hello world

从一个简单的程序开始解释,将下面的内容放进test.go文件中,路径随意:

package mainimport ("fmt"
)func main() {fmt.Println("Hello World")
}

Go通过包的方式管理程序,每个Go源代码文件都必须声明自己所在的包,正如上面的package main声明自己所在的包是main包。

每个程序都必须有一个main包,main包作为整个程序的编译入口包,main包中的main()函数作为程序的执行入口。

import关键字用来导入其它包,导入某个包之后就能在当前文件中使用这个包中的函数,例如上面的main包导入fmt包后,可以使用fmt包中的函数Println()。

然后可以使用go的build工具编译这个test.go文件:

$ go build test.go

编译后,将在当前路径下生成一个可执行二进制文件:Windows下生成的是test.exe文件,Unix下生成的是test文件。既然是可执行文件,当然可以直接执行:

$ ./test

将输出"Hello World"。

也可以直接通过go的run工具将编译和运行两个步骤合二为一:

$ go run test.go
Hello World

go run不会生成可执行的二进制文件,它实际上是将编译得到的文件放进一个临时目录,然后执行,执行完后自动清理临时目录。

关于包和go文件

每个go代码文件只能且必须使用package语句声明一个包,也就是说一个文件中不能包含多个包。

Go中有两种类型的包,或者说有两种类型的文件:

  1. 编译后成为可执行文件的包,也就是main包编译后的得到的文件
  2. 编译后成为共享库的包,只要go程序文件中声明的不是main包,就是库文件

注意:
在go的官方文档中将go的二进制可执行程序称为命令,有时候还会将go的源代码文件称为命令的源文件。可执行程序和包相反,包一般是作为"库"文件存在,用于导入而非用于执行

共享库中包含一些函数,这些函数比较通用,所以放进共享库方便函数复用。例如fmt包中的Println函数,到处都在使用这个函数,且因为fmt包是标准库(Standary library),无论是谁都可以去使用这个包。

有两种类型的库文件:标准库和第三方的库。标准库是随Go安装的时候放在go安装目录下的($GOROOT/src/),第三方库是放在workspace下的。关于workspace后文再说。

共享库可以被import导入(例如fmt包)。由于导入操作是在编译期间实现的,共享库中不应该包含任何输出型语句。

Go中对库文件要求比较严格,或者说强制性的规范。它要求库文件中package声明的包名必须和目录名称相同,且同一个目录下只允许有一个包,但同一个目录下可以有多个库文件片段,只不过这些库文件中必须都使用package声明它的包名为目录名。例如:

src/mycode|- first.go|- second.go|- third.go

如果这三个文件都是库文件,则它们都必须且只能使用package mycode声明自己的包为mycode。go build的时候,会将它们合并起来。如果声明的包名不是mycode,go build会直接忽略它。

当然,对main包就无所谓了,它不是库文件,可以放在任何地方,对目录名没有要求。但如果使用go install,则有额外的要求,见后文。

库文件中的大小写命名

Go通过名称首字母的大小写决定属性是否允许导出:

  • 首字母大写的属性是允许导出的属性
  • 首字母小写的属性不允许被导出

所以当库文件被导入时,只有这个库文件中以大写字母开头的常量、变量、函数等才会被导出,才可以在其他文件中使用。

例如,库文件abc.go中:

func first() {}
func Second() {}

当导入这个包的时候,由于first()函数首字母小写,外界无法使用它,它只能在自己的包abc.go中使用,对外界不可见。大写字母开头的Second()函数会被导入,所以可用。

工作空间(workspace)

速览

  • 通过环境变量GOPATH设置workspace的路径
  • Go编程人员一般将它们的Go代码放在一个workspace下,当然,这不是必须的
  • workspace包含一个或多个版本控制系统的仓库(如git)
  • 每个仓库包含一个或多个package
  • 每个package由单个目录下的一个或多个Go源文件组成,它们都必须声明目录名作为它们的包名
  • package的目录路径决定导入包时import的路径

Go和其它编程语言在组织项目的时候有所不同,其它语言一般每个项目都有一个单独的workspace,且workspace一般和版本控制仓库进行绑定。

现在设置GOPATH环境变量,假设设置为/gocode

echo 'export GOPATH=/gocode' >>/etc/profile.d/gopath.sh
chmod +x /etc/profile.d/gopath.sh
source /etc/profile.d/gopath.sh

go env GOPATH确定是否正确:

$ go env GOPATH
/gocode

workspace目录结构

每个workspace都是一个目录,这个目录下至少包含三个目录:

  • src:该目录用于存放Go源代码文件(也称为命令的源文件)
  • bin:该目录用于存放可执行命令(即构建后可执行的二进制go程序,也称为命令文件)
  • pkg:该目录用于存放共享库文件(即构建后非可执行程序的库包,也称为包对象文件)

括号中给的名称是go官方文档中常见的别名称呼。

所以,先创建这3个目录

mkdir -p /gocode/{src,pkg,bin}

GOPATH和GOROOT环境变量

GOPATH环境变量指定workspace的位置,用来指示go从哪里搜索go源文件/包,例如import时从哪个路径搜索包并导入。GOROOT环境变量用于指定go的安装位置。go需要导入包时,会从GOPATH和GOROOT所设置的位置处搜索包。

默认位置为$HOME/go(Unix)或%USERPROFILE\go%(Windows)。可以手动设置GOPATH环境变量的路径从而指定workspace的位置,可以指定为多个目录,多个目录时使用冒号分隔目录(Unix系统)或使用分号分隔目录(Windows系统)。注意,绝对不能将其设置为go的安装目录,即不能和GOROOT环境变量重复。

例如,windows下设置d:\gocode目录为GOPATH的路径:

setx GOPATH d:\gocode

Unix下设置$HOME/gocode目录为GOPATH的路径:

mkdir ~/gocode
export GOPATH=~/gocode
echo 'GOPATH=~/gocode' >>~/.bashrc

go envgo env GOPATH命令可以输出当前有效的GOPATH路径。

$ go env | grep GOPATH
GOPATH="/root/gocode"$ go env GOPATH
/root/gocode

go build

先写两个go文件,一个是可执行go文件test.go,一个是共享库strutils.go,将它们放在workspace的src下。

$ mkdir -p $GOPATH/src/{hello,strutils}
$ tree -C
.
├── bin
├── pkg
├── src
│   ├── hello
│   │   └── test.go
│   └── strutils
│       └── strutils.go

注意,上面故意将test.go放在名为hello的目录下,可以将其放在src下的任何非库文件目录下(例如不能放进strutils目录下),名称不要求。

hello/test.go的内容如下:

package mainimport ("fmt""strutils"
)func main() {fmt.Println("Hello World")fmt.Println(strutils.ToUpperCase("hello world"))
}

strutils/strutils.go的内容如下:

package strutilsimport ("strings"
)func ToUpperCase(s string) string{return strings.ToUpper(s)
}func ToLowerCase(s string) string{return strings.ToLower(s)
}

go build可以用于编译,编译时会对import导入的包进行搜索,搜索的路径为标准库所在路径$GOROOT/src、workspace下的src目录。它只会生成额外的可执行文件放在当前目录下,不会生成额外的库文件。但需要注意,生成的可执行文件名称可能会出乎意料:

例如进入到目录src/hello下,对test.go的文件进行编译,以下三种build路径都可用成功编译:

cd src/hello
go build             # 生成的可执行文件名为hello
go build .           # 生成的可执行文件名为hello
go build test.go     # 生成的可执行文件名为test

前两者是等价的,当go build以目录的形式进行编译,则生成的可执行文件名为目录名。当go build以go代码文件名的方式进行编译,则生成的可执行程序名为go源码文件名(去掉后缀.go或增加后缀.exe)。

go install

go还有一个工具install,go install的操作称为安装,将文件安装到合适的位置。go install时会先进行编译,然后将编译后的二进制文件保存到workspace的bin目录下,将编译后的库文件(称为包对象文件,以".a"为后缀)放在pkg目录下。

注意,go install必须先进入到$GOPATH/src,且只能对目录进行操作,不能对具体的go文件操作,因为go认为包和目录名相同。给go install指定一个目录名,就表示编译这个包名。

例如,对src/hello下的test.go进行安装,由于它导入了strutils包,所以会自动将strutils也安装好:

$ cd $GOPATH/src
$ go install hello
$ tree $GOPATH
/gocode
├── bin
│   └── hello           # 二进制程序文件名为hello,而非test
├── pkg
│   └── linux_amd64
│       └── strutils.a  # 库文件
└── src├── hello│   └── test.go└── strutils└── strutils.go

还可以单独对库文件进行安装:

$ rm -rf $GOPATH/bin/* $GOPATH/pkg/*
$ cd $GOPATH/src
$ go install strutils
/gocode
├── bin
├── pkg
│   └── linux_amd64
│       └── strutils.a
└── src├── hello│   └── test.go└── strutils└── strutils.go

如果省略目录名,则表示对当前目录下的包进行安装:

$ cd $GOPATH/src/hello
$ go install

再次提醒,go install前先进入到$GOPATH/src目录下。

由于go install可以直接安装二进制文件到$GOPATH/bin,所以出于方便执行这些二进制程序,可以将这个目录放进PATH环境变量。

$ export PATH=$PATH:`go env GOPATH`/bin

构建go程序的规范建议

1.由于可以将所有go项目放在同一个$GOPATH目录下,为了区分src下的项目目录和库文件目录,建议将每个项目目录设置深一点

例如:

bin
pkg
src|- /first/project|- main.go|- myliba|- a.go|- b.go|- mylibb|- c.go|- d.go|- /second/project|- main.go|- lib|- a.go|- b.go

2.go install时,先进入到项目目录下

3.库文件的名称(也是目录名)要选取合理,尽量短,但却尽量见名知意,也尽量减少名称重复的几率

例如util这种名称到处都是,可以修改为numutil、nameutil等。

Go基础系列:构建go程序相关推荐

  1. 【计算机基础系列文章(一)】计算机简介

    什么是计算机 计算机(computer)俗称电脑,是现代一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能.是能够按照程序运行,自动.高速处理海量数据的现代化智能 ...

  2. .NET Core 小程序开发零基础系列(2)——小程序服务通知(模板消息)

    基于上一篇文件".NET Core 小程序开发零基础系列(1)--开发者启用并校验牵手成功"的反映,个人觉得效果很不错,大家对公众号开发还是有很大需求的,同时也收到了很多同学的问题 ...

  3. Foundatio - .Net Core用于构建分布式应用程序的可插拔基础块

    简介 Foundatio - 用于构建分布式应用程序的可插拔基础块 •想要针对抽象接口进行构建,以便我们可以轻松更改实现.希望这些块对依赖注入友好.•缓存:我们最初使用的是开源 Redis 缓存客户端 ...

  4. Java零基础系列001——第一个程序

    Java零基础系列001--第一个程序 public class Welcome {public static void main(String[] args) {//args为arguments的缩 ...

  5. Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务(三):RSA(RS512) 签名 JWT(附demo)

    系列 云原生 API 网关,gRPC-Gateway V2 初探 Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇 Go + gRPC-Gateway(V2) ...

  6. STM32 基础系列教程 40 - Lwip_mqtt

    前言 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级&qu ...

  7. STM32 基础系列教程 39 - Lwip_tftp

    前言 文件传输协议(英文:File Transfer Protocol,缩写:FTP)是用于在网络上进行文件传输的一套标准协议,使用客户/服务器模式.它属于网络传输协议的应用层.文件传送(file t ...

  8. STM32 基础系列教程 22 - CAN

    前言 CAN 是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议.在汽车产业中,出于对安全性.舒适性.方便性.低公害.低成本的要求,各种各样的 ...

  9. 大数据入门基础系列之初步认识大数据生态系统圈(博主推荐)

    不多说,直接上干货! 之前在微信公众平台里写过 大数据入门基础系列之初步认识hadoop生态系统圈 http://mp.weixin.qq.com/s/KE09U5AbFnEdwht44FGrOA 大 ...

最新文章

  1. linux下的PHP+Mysql+PHPWind实现
  2. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)
  3. tp3.2 复合查询
  4. 用框图说明计算机控制系统,计算机控制系统试题
  5. 设计某高校学生选课管理系统
  6. Untiy相机实现游戏透视效果
  7. 腾讯地图获取经纬度 Java计算距离工具类
  8. 干货!国外关于高速PCB设计的技术书籍和资料介绍
  9. cad画多段线时不显示轨迹_为什么CAD绘图编辑拖动时看不到预览效果?
  10. http 传输原理及格式
  11. Qt学习之Windows下Qt应用程序打包成exe安装包
  12. android bea拷贝,从Android开发中学到一些东西
  13. 尝试 Stable Diffusion(通过Google Colab)
  14. vlc 详细使用方法:libvlc_media_add_option 函数中的参数设置
  15. [neovim/nvim] LSP 与代码补全配置笔记
  16. 首席新媒体运营黎想教程:产品运营怎么使用思维导图?
  17. 杉达计算机科学与技术专业怎么样,上海杉达学院专业排名,查看哪些专业好?...
  18. 人类社会发展对数学的影响
  19. 学好PS,走到哪里都不怕
  20. 找桌面背景(win10的和360的)

热门文章

  1. 中国血液制品行业供给预测与投资风险分析报告2022版
  2. 农业谋定竞争力-农业大健康·万祥军:质量效益促品牌农业
  3. 泛亚凭借一粒薏米-农业大健康·田亚:对话农民丰收节交易会
  4. HCNA(012-211) 试题解析
  5. (WPF)WPF要点之事件-深入浅出WPF笔记
  6. “盗”亦有道,关于robots协议
  7. 第一个python命令
  8. caffe中Makefile.config详解
  9. Airtable(数据管理)
  10. OleDb执行Oracle带自定义函数的SQL深度历险