要学会两件事
- 封装代码➡函数
- 根据功能分模块文件➡工程文件的管理
如何编写go代码
代码组织
go应用使用包和模块来组织代码,包对应到文件系统就是文件夹,模块就是**xxx.go**
的go源文件。一个包中会有多个模块,或者多个子包。
?go项目管理工具
早期的go项目使用gopath来管理项目,不方便而且容易出错,从golang 1.11 开始使用gomod管理项目,当然还有第三方模块例如govendor,我们给大家结束gomod的使用(知乎上有详情,稍后看看)
实现步骤
- 创建项目
- 创建项目文件夹mypro
- cmd定位→输入
code .
创建代码文件
- 初始化项目
go mod init mypro(项目名称)
执行之后会生成go.mod
文件 - 创建包→创建模块
- 新建文件夹user,创建user.go模块,写入一些东西,package xxx与包同名
- 创建main.go模块,main主包下的main函数是项目的入口
- 新建文件夹user,创建user.go模块,写入一些东西,package xxx与包同名
- 相互调用
引入包→调用
包
包的意义就在于避免重复写代码,一个文件夹,就是一个包;Go语言是通过包来管理文件的
基本知识
包的概念
- 什么是包?
- 包(package)是多个Go源码的集合, 是一种高级的代码复用方案,
- 一个文件夹 = 一个包,还要子包;一个文件=一个模块
- 一个包的源代码保存在一个或多个以
.go
为文件后缀名的源文件中,通常一个包所在目录路径的后缀是包的导入路径。
- 要求
- 什么是包内包外?
——同一包声明,就是包内 = 同一文件夹下;包外,就是不同文件夹之间
包的作用
- 内置包
——Go语言为我们提供了很多内置包,如fmt、os、io等,可以现成直接import 获得使用 - 当程序文件很多的时候,可以很好地管理项目,相当于创建了共享中心
——通过import"B"
可以调用在A中,使用B包中定义的函数/方法等等 - 区分相同名字的函数、变量等标识符
——解释:同一个包下,函数名具有唯一性,不同包下可以声明定义名字相同的两个函数 - 控制函数、变量等访问范围,即作用域
包的要求
- 同一个包(文件夹)下,所有go文件都只能用同一个package,也就是每个文件开头的package 后面的名字要一致。
- 只有两种情况:
使用场景 | |
---|---|
package main |
含有main函数的主文件 |
package 文件夹名 (不是文件名) |
不含main函数但是可含init函数的文件夹内的文件 |
+ import后面的其实是GOPATH开始的相对目录路径,包括最后一段。但由于一个目录下只能有一个package,所以import一个路径就等于是import了这个路径下的包。(现在用gomod就不太用这个)
+ 注意,这里指的是"直接包含”的go文件。如果有子目录,<font style="color:#E8323C;">那么子目录的父目录是完全两个包。</font>
- 实例
——比如你实现了一个计算器package,名叫calc,位于calc目录下;仅想给别人一个使用范例,于是在calc下可以建个example子目眼(calc/example/),这个子 目录里有个example.go
(calc/example/example.go) 。此时,example.go
可以是main包, 里面还可以有个main函数。 - 重名问题
——解决方法:起别名
语法
如何创建包?
:::info 前言:包要在环境变量里
:::
- 以前,对于一个较大的应用程序,我们应该将它的功能性分隔成逻辑的单元,分别在不同的包里实现。我们创建的的自定义包最好放在GOPATH的src目录下(或者GOPATH src的某个子目录)。
- 现在多用gomod
:::info 步骤
:::
- 创建文件夹/包
- 创建一个
xxx.go
文件 package xxx
- 代码包中的源码文件名可以是任意的。但是,第一行必须是package xxx,声明该文件归属的包
pakage main
或者package calc(文件夹名)
引入包
以前,引入的包,也要保证在环境变量里,现在用gomod管理
语法import "xxx"
//方式1
import "fmt"
import "os"
//方式2,最常用
import (
"fmt"
"os"
)
//方式3:(.)点操作,下面操作无需 包.函数/方法,直接写函数和方法
import . "fmt"
func main{
Println("on testing")//好处是简约了一些
Println("os,Args = ", Args)
//坏处是当包很多的时候,一旦变量名与包重名,或者包重名,程序就会崩
}
方式4:地址
包名是从$GOPATH/src/后开始计算的,使用/进行路径分隔
实例::::info 给包起别名
:::
目的:避免包的同名冲突,或者是包名比较长,不好调用
注意:包名不可重复
:::info 忽略此包
:::
我们知道引入了包不用,是会把报错的,那么怎么在不删除引入包命令的条件下,不报错呢?
import _ "B"
更重要的是,可以用此命令只引入并执行该包中的init函数,而不使用该包中的其他定义好的函数
调用包
- 语法:
包.xxx
- 函数可见性
- public:首字母大写,可被包外访问
- private:首字母小写,仅包内成员可以访问
?包管理工具 go module
go module是go 1.11后的新加的特性,用来管理包的依赖关系,简称go mod,网站最详细教程
go mod使用方法
最常用,就开头两个
- 初始化模块
go mod init <项目模块名称>
- 依赖关系处理,根据go.mod文件
go mod tidy
- 将依赖包赋值到项目下的vendor目录
go mod vendor
如果包被屏蔽(墙),可以使用这个命令,随后使用 go build -mod=vendor编译 - 显示依赖关系
go list -m all
- 显示详细依赖关系
go list -m -json all
- 下载依赖
go mod download [path@version]
[path@version]是非必写的
实例
:::info 自建包然后引用
:::
- step_1
- 新建文件pro02,创建代码
- 在终端,初始化模块
go mod init duoke360.com/pro02
域名duoke360.com是什么???
- step_2
- 新建main.go文件,新建service包,分别写入内容
- 终端转移到该目录下
cd .\service\
- 编译
go build
- 新建main.go文件,新建service包,分别写入内容
- step_3
- 在main文件内,引入
import "duoke360.com/pro02/service"
- 即可调用包内函数
service.<函数/方法>
- 在main文件内,引入
:::info 引入远程包
:::
- 寻找下载地址
找gin包 - 下载
go get <网址>
-u是什么??? - 即可引用,引入语法网址提供
main函数
:::info main特点
:::
- 无参数、无返回值
- main函数必须要在main包里
- 可执行程序内必须有,且仅有一个main的包
- 应用程序入口
- 必须是main包
- 必须是main方法
- 文件名不一定是main.go
原理解读:
在Go语言里,命名为main的包具有特殊的含义。Go语言的编译程序会试图把这种名字的包编译为二进制可执行文件。所有用Go语言编译的可执行程序都必须有一个名叫main
的包。一个可执行程序有且仅有一个main包。当编译器发现某个包的名字为main时,它一 定也会发现名为main()的函数,否则不会创
建可执行文件。main() 函数是程序的入口,所以,如果没有这个函数,程序就没有办法开
始执行。程序编译时,会使用声明main 包的代码所在的目录的目录名作为二进制可执行文
件的文件名。
思考:
由于main函数在可执行程序里的唯一性与必要性,包可分为有main函数的,和没有main函数的
- 有main函数的必定可划分为执行程序,且开头必然是 package main,
- 无main函数的,只能是引用,开头可以是 package xxx文件夹名
环境变量
环境变量是什么?
- 作用:
环境变量的作用就是,指明操作系统的重要目录在哪里 - systemroot——环境变量
程序在运行时需要从系统目录读取文件,你说它是在磁盘上挨个找这个目录呢?还是让操作系统告诉他目录——显然后者更高效快捷,故用systemRoot来指明系统目录所在的位置,这就是所谓的环境变量<font style="color:#DF2A3F;">%xxx%</font>
表示的就是某环境变量
➡windows系统目录 - Windows中常见的环境变量有
- %SYSTEMROOT%:操作系统的根目录,通常是 C:\Windows。
- %WINDIR%:同 %SYSTEMROOT%,指向操作系统的根目录。
- %SYSTEMDRIVE%:系统所在的驱动器,通常是 C:。
- %HOMEDRIVE%:用户主目录所在的驱动器,通常是 C:。
- %HOMEPATH%:用户主目录的路径,通常是 \Users{用户名}。
- %USERPROFILE%:当前用户的配置文件目录,通常是 C:\Users{用户名}。
- %APPDATA%:当前用户的应用程序数据文件夹路径,通常是 C:\Users{用户名}\AppData\Roaming。
- %LOCALAPPDATA%:当前用户的本地应用程序数据文件夹路径,通常是 C:\Users{用户名}\AppData\Local。
- %TEMP%** 或 **%TMP%:当前用户的临时文件夹路径,通常是 C:\Users{用户名}\AppData\Local\Temp。
- %PROGRAMFILES%:系统的程序文件夹路径,通常是 C:\Program Files。
- %PROGRAMFILES(X86)%:在64位系统上,用于存放32位程序的文件夹路径,通常是 C:\Program Files (x86)。
- %COMMONPROGRAMFILES%:程序文件的公共文件夹路径,通常是 C:\Program Files\Common Files。
- %COMMONPROGRAMFILES(X86)%:在64位系统上,32位程序的公共文件夹路径,通常是 C:\Program Files (x86)\Common Files。
- %PATH%:可执行文件的搜索路径。多个路径使用分号分隔。
- %PATHEXT%:系统可识别的可执行文件扩展名列表。
- %COMSPEC%:命令处理器的路径,通常是 C:\Windows\System32\cmd.exe。
- %NUMBER_OF_PROCESSORS%:计算机中的处理器数量。
- %PROCESSOR_ARCHITECTURE%:处理器架构类型,例如 AMD64 或 x86。
- %PROCESSOR_IDENTIFIER%:处理器的描述字符串。
- %ALLUSERSPROFILE%:所有用户的公共配置文件目录,通常是 C:\ProgramData。
- %PUBLIC%:公共用户文件夹,通常是 C:\Users\Public。
分类
- 分为系统变量和用户变量
- 区别
环境变量是root的环境变量,作用于所有用户;用户环境变量,仅作用于当前电脑系统登录的账户
(也就是说如果你电脑账户只有一个,那就无所谓)
怎么用?
PATH和编程息息相关的环境变量
- 系统会尝试在Path指明的目录中查找cmd这个程序,找到就运行,找不到就报错
之所以能运行是因为Path环境变量有cmd所在的地址 - 如果我们要在dos上运行一个程序,那怎么办呢?
- 把文件放到系统目录下
- 环境变量里添加新地址(要运行的程序所在的地址)
GO实际运用
- goland软件支持为项目独立设置环境变量,教程
- GOPATH环境变量默认为go语言安装的位置,可修改,貌似Path也添加了
- goroot就是go安装的根目录, gopath就是go项目所在的路径, 高版本go项目已经不再依赖gopath来管理项目,使用go mod来管理项目。
?创建文件步骤
问题
- 创建新模块,包如何声明?
- 环境变量需要创建吗?
- gopath
- 系统里path的设置,问,GOPATH和PATH里的什么关系???
- goland软件支持为项目独立设置环境变量
- gomod???
- 第三方管理软件
- 需要引入包吗?
- 同一个包内需要引用,不同包内无需引用
- 引用语法
- 调用时候,
包名.xxx
且要求函数/方法/变量…必须大写
工作区
Go代码必须放在工作区中。工作区其实就是一个对应于特定工程的目录,它应包含3个子 目录: src目录、pkg目录和bin目录。 + src目录:用于以代码包的形式组织并保存Go源码文件。(比如: .go.c.h.s等) + pkg目录:用于存放经由go install命令构建安装后的代码包(包含Go库源码文件)的“.a”归档文件。 + bin目录:与pkg目录类似,在通过go install命令完成安装后,保存由Go命令源码文件生成的可执行文件。(exe?)简化:
目录src用于包含所有的源代码,是Go命令行工具一个强制的规则,必须有,而pkg和bin则无需 手动创建,如果必要Go命令行工具在构建过程中会自动创建这些目录。 需要特别注意的是,只有当环境变量GOPATH中只包含一个工作区的目录路径时,goinstall 命令才会把命令源码安装到当前工作区的bin目录下。若环境变量GOPATH中包含多个工 作区的目录路径,像这样执行go install命令就会失效,此时必须设置环境变量GOBIN。
同一目录
- 创建src文件夹
分文件编程(多个源文件),必须放在src目录,即我们创建一个src文件夹,等会在里面创建文件 - 设置GOPATH环境变量
注意是src所在地地址,不要进去src,据我所知,有两种方式- 一种是在我的电脑的高级系统设置里,修改环境变量(在DOS窗口输入 go env 可查看相关的环境变量地设置)
- 一种是用IDE,我用的GOPATH可以为每个工程设置单独的环境变量
- 创建文件
- 同一个目录下,包名必须一致
- 同一个目录下,调用别的文件的函数,直接调用,无需引入包名(实例中,可在main函数下,直接引用test)
- main函数必须有,又必须在package main之下,故主文件,其实必然是package main开头
(什么情况是package xxx文件夹名的?看下方的不同目录情况)
:::info 画图实例展示
:::
不同目录
- 创建文件夹和写package xxx
在src下,创建别的文件夹,不同目录,包名可以不是main,但需要和文件夹名统一(package xxx文件夹名的) - 环境变量配置
创建了新的文件夹之后,同样要设置环境变量,在IDE里设置即可(???若在环境变量里,创建文件夹,需要重新再设环境变量吗?) - 要在A包中引入B包的函数Add
- 此函数必须大写开头 Add
- 代码开头
package "A"
+ 代码过程A.Add(...)
(有的时候,要go build 一下B包,产生可执行文件.exe
,才能在A包中显现/提示出来)
:::info 实例
:::
src文件夹下
main.go文件
calc.go文件
文件执行步骤
文件执行步骤
init函数作用:
- 引入别的包,该包中,若自定义的函数没被引用,是不会执行的,所以诞生了init函数,只要导入B包,B包的init函数就会执行
- 若主文件,本身也有init函数,那么也会比main函数先执行
import _ "A"
实际是引入该包,不使用包里的函数,而是调用了包里的init函数
init 函数
go语言中init函数用于包(package)的初始化,该函数是go语言的一个重要特性。 有下面的特征:先看完下面的文件创建步骤,再看这个init包
- 作用
init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等 - 要求
- 每个包可以拥有多个init函数
- 包的每个源文件也可以拥有多个init函数
- init函数不能被其他函数调用,而是在main函数执行之前,自动被调用
- 执行顺序
- 同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)
- 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
init函数和main函数的异同
相同点:两个函数在定义时不能有任何的参数和返回值,且Go程序自动调用。
不同点:
init可以应用于任意包中,且可以重复定义多个。
main函数只能用于main包中,且只能定义一个。
:::info 两个函数的执行顺序
:::
- 对同一个go文件
init()调用顺序是从上到下的。 - 对同一个package中不同文件
是按文件名字符串比较“从小到大”顺序调用各文件中的init()函数。 - 对于不同的package, 1. 如果不相互依赖的话,按照main包中”先import的后调用”的顺序调用其包中的init(), 2. 如果package存在依赖,则先调用最早被依赖的package中的init(),最后调用main函数。
- 如果init函数中使用了println()或者print()
你会发现在执行过程中这两个不会按照你想象中的顺序执行。这两个函数官方只推荐在测试环境中使用,对于正式环境不要使用。
常用命令
:::info 最常用:
:::
- go build xxx编译包和依赖
go build xxx
+./xxx(可执行文件)
- go run xxx运行
- go env xxx 显示当前go的环境的信息
- go get
- 找到项目
go mod init 项目名称
???go get xxx
- 找到项目
go list
列出包
git
版本管理,主要用于github上下载非常方便,git clone ...