### 概述
go代码必须放在工作区中.工作区其实就是一个对应于特定工程的目录,它应包含3个子目录 : src目录,pkg
目录,和bin目录 .
* src : 用于以代码包的形式组织并保存go源码文件.(比如 : go.c .h .s等)
* pkg : 用于存放经由go install命令构建安装后的代码包(包含go库源码文件)的 ".a"归档文件
* bin : 与pkg目录类似,在通过go install命令完成安装后,保存由go命令源码文件生成的可执行文件 .
目录src用于包含所有的源代码,是go命令行工具一个强制的规则,而pkg和bin则无需手动创建,如果必要go
命令行工具在构建过程中会自动创建这些目录.
特别需要注意的是,只有当环境变量GOPATH中只包含一个工作区的目录路径时,go install命令才会把命令
源码安装到当前工作区的bin目录下.若环境变量GOPATH中包含多个工作区的目录路径,像这样执行go install
命令就会失效,此时必须设置环境变量GOBIN.
### GOPATH设置
为了能够构建这个工程,需要先把所需工程的根目录加入到环境变量GOPATH中.否则,即使处于同一工作目
录(工作区) ,代码之间也无法通过绝对代码包路径完成调用 .在实际开发环境中,工作目录往往有多个.这些
工作目录的目录路径都需要添加至GOPATH . 当有多个目录时,请注意分隔符,多个目录的时候Windows是
分好,linux是冒号,当有多个GOPATH时,默认会将go get的内容放在第一个目录下 .
~~~
go env //查看go的环境变量
~~~
### 包
所有go语言的程序都会组织成若干组文件,每组文件被称为一个包,这样每个包的代码都可以作为很小的服
用单元,被其他项目引用 . 一个包的源代码保存在一个或多个以.go为文件后缀名的源文件中, 通常一个包
所在目录路径的后缀是包的导入路径 .
#### 自定义包
对于一个较大的应用程序,我们应该将他们的功能分隔成逻辑单元,分别在不同的包里实现.我们创建的自定
义包最好放在GPPATH的src目录下(或者GOPATH src的某个子目录) . 在go语言中,代码包中的源码文件名
可以是任意的.但是,这些任意名称的源码文件都必须以包声明语句作为文件的第一行,每个包都对应一个
独立的名字空间 .
~~~
package packageName
~~~
**包中成员以名称首字母大小写决定访问权限 :**
* public : 首字母大写,可被包外访问
* private : 首字母小写,仅包内成员可以访问
**注意 : 同一个目录下不能定义不同的package**
### main包
在go语言中,命名为main的包具有特殊的含义 . go语言的编译程序会试图把这种名字的包编译为二进制可
执行文件.所以用go语言编译的可执行程序都必须有一个名叫main的包.一个可执行程序有切只有一个
main包 . 当编译器发现某个包的名字为main时,它一定也会发现名为main()的函数,否则不会创建可执行文
件. main()函数是程序的入口,所以,如果没有这个函数,程序就没有办法开始执行.程序编译时,会使用声明
main包的代码所在的目录的目录名作为而进行可执行文件的文件名 .
### main包和init函数
go里面有两个保留的函数:init函数(能够应用于所有的package)和main函数(只能应用于package main).这
两个函数在定义时不能有任何的参数和返回值.虽然一个package里面可以写任意多个init函数 ,但这无论
是对于可读性还是以后的可维护性来说,我们都强烈建议用户在一个熬成卡个中每个文件只写一个init函数
.go程序会自动调用init()和main(),所以你不需要在任何地方调用者两个函数,每个package中的init函数都是
可选的,但package main就必须包含一个main函数 . 每个包可以包含任意多个init函数,这些函数都会在程
序执行开始的时候被调用,所有被编译器发现的init函数都会安排在main函数之前执行 .init函数用在设置
包,初始化变量或者其他要在程序运行前优先完成的引导工作 .程序的初始化和执行都起始于main包.如果
main包还导入了其他的包,那么久会在编译时将它们依次导入.有时一个包会被多个包同时导入,那么它指
挥被导入一次(例如很多包可能都会用到fmt包,但它只会被导入一次,因为没有必要导入多次) .当一个包被
导入时,如果该包还导入了其他的包,那么会将其他包导入进来,然后在对这些包中的包级常量和变量进行
初始化,接着执行init函数(如果有的话) ,一次类推.等所有被导入的包都加载完毕了,就会开始对main包中的
包级常量和变量进行初始化,然后执行main包中的init函数(如果存在的话),最后执行main函数.下图详细的
解释了整个执行过程 .

### _ 操作
~~~
import _ "fmt" //忽略此包
~~~
### 总结
声明语句最先执行, 然后是init()函数,再然后是main()函数.
- 基本语法
- 申明变量
- 常量
- 数据类型
- 强制类型转换
- 获取命令行参数
- 指针
- 概述
- new函数
- 函数
- 概述
- 不定参数类型
- 有返回值
- 函数类型
- 回调函数
- 匿名函数和闭包
- 延迟调用defer
- 工程管理
- 工作区
- src,pkg和bin目录
- 复合类型
- 概述
- 数组
- 概述
- 声明并初始化
- 拷贝传值
- slice
- 概述
- 创建切片
- 切片截取
- 切片和底层数组的关系
- slice常用方法
- 切片做函数参数
- map
- 概述
- map操作
- 结构体
- 概述
- 结构体初始化
- 结构体比较
- 结构体作为函数参数
- 结构体前加&
- 面向对象
- 概述
- 匿名组合
- 方法
- 值语义和引用语义
- 方法集
- 方法的继承
- 方法重写
- 方法值
- 接口
- 接口定义和实现
- 多态的表现
- 接口继承
- 接口转换
- 空接口
- 类型断言
- 异常处理
- error接口
- panic
- recover
- 文本文件处理
- 字符串操作
- 正则表达式
- json处理
- 文件操作
- 标准设备文件操作
- 并发编程
- 概述
- 并发和并行
- go语言并发优势
- goroutine
- goroutine概述
- 创建goroutine
- 主协程先退出
- runtime包
- Gosched
- Goexit
- GOMAXPROCE
- channel
- 多资源竞争
- channel类型
- 无缓冲channel
- 有缓冲channel
- 关闭channel
- 单向channel
- 单向channel特性
- 定时器
- Timer
- Ticker
- select
- select作用
- 超时
- sync
- 竞争状态
- 网络编程
- 网络概述
- 网络协议
- 分层模型
- 网络分层架构
- 层与协议
- 每层协议的功能
- 链路层
- 网络层
- 传输层
- 应用层
- socket编程
- 组合和继承
- 注意事项
- 细节
- go语言实现队列
- google工程师golang
- 基础语法
- 内建容器
- 面向"对象"
- 依赖管理
- 面向接口
- 函数式编程
- 错误处理和资源管理
- 测试与性能调优
- goroutine
- channel
- golang问题集
- 断言和类型转换
- Go语言圣经
- 入门
- 程序结构
- 命名
- 声明
- 变量
- 赋值
- 类型
- 包和文件
- 作用域
- 基础数据类型
- 整数
- 浮点数
- 复数
- 布尔型
- 字符串
- 常量
- 复合数据类型
- 数组
- slice
- map
- 结构体
- json
- 文本和HTML模板
- 函数
- 函数声明
- 错误
- 函数值
- 匿名函数
- defer
- panic
- recover
- 方法
- 方法声明
- 指针对象的方法
- 封装
- 接口
- 说明
- 接口是合约
- 实现接口的条件
- 接口值
- 类型断言
- 通过类型断言询问行为
- 类型开关
- Goroutines和Channels
- 协程
- channels
- 无缓冲channel
- 串联的channel
- 有缓冲channel
- 并发的循环
- select多路复用
- 并发的退出
- 并发问题的自我思考
- 基于共享变量的并发
- 竞争条件
- 互斥锁
- 读写锁
- 内存同步
- sync.Once
- 协程和线程
- 包和工具
- 测试
- 反射
- 什么是反射
- 为什么需要反射
- reflect.Type和reflect.Value
- 通过reflect.Value修改值
- 底层编程
