go中包到定义
包 package,是多个go源码的集合。
是一种高级的·代码复用·的方案。
go语言为我们提供了很多的内置包,比如fmt,strconv,strings,sort,errors, time,
encoding/json os io等内置包,
strconv:
包strconv主要实现对字符串和其他基本数据类型之间的转换。基本数据类型包括:布尔、整型(包括有/无符号、二进制、八进制、十进制和十六进制)和浮点型等。
strings包主要是处理字符串的。
sort是排序包
errors是错误处理包
time是时间包
所谓的内置包,就是我们在进行代码开发的时候,可以直接使用,而不需要下载。
go中的包分为3大类,内置的包,自定义的包,第三方包(别人写的 git上开源的包)
自定义包,就是自己写的一个目录,目录中可以有很多的.go文件,文件中我们可以定义一些变量,函数,或者结构体,这样我们就可以使用了。
一个go项目中,最多只能有一个main包和main方法。
一个包中的.go文件的package 后面的包名,可以和所在的目录名相同,当然也可以不相同,但是一般来说,我们建议是写成一样的。
首字母大写,代表是公有
首字母小写,代表是私有
.go文件中的变量和函数,如果首字母是大写的,说明这个变量或函数是公有的,也就是说,可以被别包中的.go文件使用,如果是小写的,则代表是私有的,则只能在自己的包中使用,不能被被的包调用。
在.go文件中,我们可以定义变量,可以定义函数,也可以定义结构体。
包名是main的包是整个项目的入口包,这种包在编译之后会得到一个可执行的文件,
而编译没有包含的源代码则不会得到可执行文件。
一个项目中,只能有一个main方法和一个main包
不同的包中的.go文件是可以同名字的。
比如有一个calc的目录,其中有一个aaa.go文件
另外还有一个tools的目录,其中也有一个aaa.go文件,这是可以的。
一个包中(目录中),可以写多个.go文件,但是不同.go中的函数名称不能重复。
一个包中的多个.go文件中的方法名不能重复。
当我们import一个包的时候,可以给起一个别名,这种做法主要是为了针对包名特别长的情况。
当我们import一个包,但是在下面的代码中没有使用,可以在包名前加一个_
第三方包: 都放在了 https:
go.sum文件是自己生成的,我们不用管它。
当我们在.go文件中import某个我们依赖的包,并且通过go mod download 或 go get xxx
或者 go mod vnedor命令来下载依赖的包的时候,如果下载成功,则会自动的在go.mod文件中自动的require 添加上。
在go中,你可以理解为是以包为单位的(及以package为单位).
在同一个目录下,所有文件的package都必须是相同的。虽然package的名字不一定是所在目录的名字,
但是一定得相同。
全局变量的使用范围是同一个包内,局部变量的使用范围是同一个{}内。
在同一个目录下,所有文件的package都是一样的,那么a.go文件中就可以去调用b.go文件中的变量,
c.go文件也可以去调用d.go文件中的变量。
注意:
- 同一个包中调用函数,函数名定义没有特定要求。
- 不同包调用函数或者变量时,函数名定义必须以大写字典开头,例如:`func Add() {}`,表示当前函数或变量是可公开调用的

go mod
在命令行中,执行 go mod命令,我们可以看到有以下一些功能可以使用:

也就是说,go mod是一个大的方面的东西,其中有很多具体的功能可以使用。
比如 go mod init 项目名
go mod tidy : 增加丢失的module ,去掉未用的module
go mod download :下载依赖的module到本地,,
放在gopath/pkg/mod/github.com中了,
这里统一存放所有下载的github中的包。
每个包都是一个文件夹。
go mod vendor :把依赖复制到vendor目录下,及会在项目下创建一个vendor目录
go mod edit : 编辑go.mod文件。
go env

自动下载
go env -w GO111MODULE=on
设置环境为国内代理
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=off
下载第三方包的几种方法
<1>go get (一般不用该方法)
该命令也是可以下载我们依赖的第三方包的,
这个方法会把依赖的第三方包下载到本地。
比如 go get github.com/shopspring/decimal
但是这个方法可能会遇到网络的问题,在国内成功的概率不是很大。
<2>go mod download
通过这种方法,依赖包会自动下载到$gopath/pkg/mod/cache/download目录中。多个项目可以共享。
注意:
使用go mod download下载第三方包的时候,首先你需要在你的项目中引入第三方包
<3>go mod vendor
该方法会把依赖的包,下载复制到当前项目的vendor目录中
<4>go mod tidy
一次性下载所有依赖的第三方包
go.mod文件
使用go mod这个依赖包管理工具,就不需要非得把项目放在gopath指定目录下,
你可以在你磁盘(电脑)的任何位置创建一个go项目,包含go.mod文件的目录也称为模块根,
也就是说,go.mod文件的出现定义了它所在的目录为一个模块。
go开发语言和编辑器(IDE)
go开发包(类似于python解释器)+ ide(golang,vscode,sublime text。。。。)
go开发包,和anaconada3,anaconda2这些差不多,都是一个开发包,有anaconda3/bin/python go/bin/go 这就是sdk
golang:跟pycharm 90%相似,jetbrains公司,idea,用来开发java的,phpstorm,pycharm,goland
1 下载go开发包(这个建议就安装在c盘)
https:
2 go的解析器下载
直接百度搜索Goland然后选择官网去下载
3 下载好了之后我们就可以在cmd中查看自己的版本
go version 查看go的版本
go env 查看go的环境变量
GO111MODULE= # 没有值或者off,表示没有开启go mode模式,用的就是gopath模式
GOROOT=c:\go # go开发包的安装路径,确认好是否对
GOPATH=C:\Users\Administrator\go # 代码存放路径,确认好是否对,以后你的go代码都放在这个文件夹下
在任意位置敲go,都有这个命令,需要把 c:\go\bin加入环境变量
go mode模式:代码可以放在任意路径
如何导入包import
在写Go代码的时候经常用到import这个命令用来导入包文件,看到的方式参考如下:
import(
"fmt"
)
然后在代码里面可以通过如下的方式调用
fmt.Println("hello world")
上面这个fmt是Go语言的标准库,他其实是去GOROOT下面加载该模块,当然Go的import还支持如下两种方式来加载自己写的模块:
相对路径:import "./model"
绝对路径:import "shorturl/model"
上面展示了一些import常用的几种方式,但是还有一些特殊的import,让很多新手很费解,下面是三种导入包的使用方法。
(1)点操作
有时候会看到如下的方式导入包 import( . "fmt" )
这个点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名.
也就是前面你调用的fmt.Println(“hello world”) 可以省略的写成Println(“hello world”)
(2)别名操作
别名操作顾名思义可以把包命名成另一个用起来`容易记忆`的名字
import( f "fmt" )
别名操作调用包函数时前缀变成了重命名的前缀,即f.Println(“hello world”)
(3)_操作
这个操作经常是让很多人费解的一个操作符,请看下面这个import
import ( “database/sql” _ “github.com/ziutek/mymysql/godrv” )
_操作其实只是引入该包。当导入一个包时,它所有的init()函数就会被执行,但有些时候并非真的需要使用这些包,仅仅是希望它的init()函数被执 行而已。
这个时候就可以使用_操作引用该包了。
即使用_操作引用包是无法通过包名来调用包中的导出函数,而是只是为了简单的调用其init函数()。
注释
在go语言中表示 多行注释使用
函数的定义和调用
函数是基本的代码块,用于执行一个任务。
Go 语言最少有个 main() 函数。
你可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
函数声明告诉了编译器函数的名称,传入的参数,返回结果的类型。
Go 语言标准库提供了多种可动用的内置的函数。
例如,len() 函数可以接受不同类型参数并返回该类型的长度。
如果我们传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。
go语言函数的一般定义格式如下:
func function_name( [parameter list] ) [return_types] {
函数体
}
函数定义解析:
- func:函数由 func 开始声明,是定义函数时候的关键字,类似于python中的def关键字
- function_name:函数名称,参数列表和返回值类型构成了函数签名。
- parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
- return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。
有些功能不需要返回值,这种情况下 return_types 不是必须的。
- 函数体:函数定义的代码集合,具体的函数逻辑
<1>函数的定义
func get_max(num1, num2 int) int {
var result int
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
<2>函数的调用
当创建函数时,你定义了函数需要做什么,通过调用该函数来执行指定任务。
调用函数,向函数传递参数,并返回值,例如:
package main
import "fmt"
func main() {
var a int = 100
var b int = 200
var ret int
ret = get_max_value(a, b)
fmt.Printf( "最大值是 : %d\n", ret )
}
func get_max_value(num1, num2 int) int {
var result int
if (num1 > num2) {
result = num1
} else {
result = num2
}
return result
}
在命令行运行go代码文件
go run xxxx.go
就像是python xxx.py文件
fmt包中的Println()和Printf()这2个函数的区别
总结:Println()可以打印所有类型的变量,并且是自动换行
Printf():f是format()的意思,及只能打印格式化的字符串
package main
import "fmt"
func main() {
num := "hello word!"
fmt.Println(num)
fmt.Printf("我要写的内容是:%s\n", num)
fmt.Printf("我要写的内容是:%s", num)
}
时间time
参考网址:http:
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Printf("current time:%v\n", now)
year := now.Year()
month := now.Month()
day := now.Day()
hour := now.Hour()
## minute := now.Minute()
second := now.Second()
fmt.Printf("%d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second)
}
什么是go语言中的包package
包(package)是多个go源码的集合,是一种高级的代码复用方案。
go语言给我们提供了很多`内置`的包,如fmt,os,io等(类似于python中的内置的包或者函数,不需要我们再额外的安装install和导入import)。
当然仅仅使用内置的包,是不能满足我们的要求的。我们可以根据自己的需要创建自己的包。
一个包可以简单理解为是一个存放.go文件的文件夹。
该文件夹下的所有.go文件都要在代码的第一行声明该文件所属的包package
package 包名
注意事项:
一个文件夹下直接包含的文件只能属于一个包package,同样的,一个包package的文件不能在多个文件夹下。
包名可以不和文件夹的名字一样,包名不能包含-符号。
包名是main的包是应用程序的入口包,这是一个特殊的包。
这种包在编译之后会生成一个可执行文件,而其他的包在编译之后不会生成可执行文件。
如果想在一个包中引用另外一个包中的标识符(比如变量,常量,类型,函数)时,则该标识符必须是对外可见的。在go语言中,只需要把标识符(比如变量,常量,类型,函数)的首字母大写就可以了,这样就是对外可见的了。
结构体中的字段名和接口中的方法名,如果首字母是大写,外部包也是可以访问这些字段和方法的。例如:
type Student struct {
Name string
class string
}
type Payer interface {
init()
Pay()
}
要在代码中引用其他包的内容,需要使用import关键字导入使用的包。具体语法如下:
import '包的路径'
import导入语句通常放在文件开头包声明语句的下面。
导入的包名需要使用双引号包裹起来。
包名是从$GOPATH/[src](https:
Go语言中禁止循环导入包。
如果只希望导入包,而不使用包内部的数据时,可以使用匿名导入包。具体的格式如下:
import _ "包的路径"

首字母大小写
golang中根据首字母的大小写来确定可以访问的权限。无论是方法名、常量、变量名还是结构体的名称。
如果首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用。
可以简单的理解成,首字母大写是公有的,首字母小写是私有的
goroot和gopath的关系和区别
<1>goroot
goroot其实就是golang语言的安装路径。
当你安装完golang之后,这个其实就已经有了
<2>gopath
作用:
(1)存放sdk之外的第三方类库
(2)自己收藏的可以复用的代码
目录结构:
gopath目录约定有3个子目录:src目录,pkg目录,bin目录。
src目录存放源代码(比如:.go .c .h .s等) 按照golang默认约定,go run,go install等命令的当前工作路径(即在此路径下执行上述命令)。
pkgn目录存放编译时生成的中间文件(比如:.a) golang编译包时
bin目录存放编译后生成的可执行文件
为了方便,可以把此目录加入到PATH变量中 ,
如果有多个gopath ,那么使用PATH变量中,如果有多个gopath,那么使用 PATH变量中,如果有多个gopath,那么使用{GOPATH/bin:}/bin添加所有的bin目录)
goland中的global gopath和project gopath

这里有俩个一个是Global GOPATH 一个是Project GOPATH
Global GOPATH是所有项目都可以使用的
Project GOPATH是只有这个一个项目可以使用的
go安装第三方库/包
参考网址:https:
<1>前提
go安装第三方库/包的前提是:必须设置gopath
linux环境:
```
vim /etc/profile
export GOROOT=/usr/local/go // 设置为你自己的go安装目录
export GOPATH=$HOME/gocode // 设置为自己的go项目的工作区间
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin // 原路径后用冒号连接新路径
source /etc/profile // 使文件立刻生效
```
mac环境:
```
cd ~
vim .bash_profile
export GOROOT=/usr/local/opt/go@1.9/libexec //golang安装路径
export GOPATH=/usr/local/Cellar/go/1.7.6 // 工作路径
export GOBIN=$GOPATH/bin // 可执行文件
export PATH=$PATH:$GOROOT/bin:$GOBIN // path导入路径
source ~/.bash_profile // 使文件立刻生效
```
win环境:
window : GOPATH,额外 安装git
其实linux和mac系统也需要git,不过这两者都默认拥有git。而windows是需要自主安装的
1. 去git官网下载git并安装
1. 再设置GOPATH:
右键我的电脑——高级系统设置——环境变量,系统变量下 点击【新建】
输入: 第1行:GOPATH 第2行:你指定路径,例如: D:\go\gopath (注意去掉末尾的分号)
<2>golang安装第三包的方式
(1)自动安装:通过`go get xxx`命令来安装
这条命令会把远端的第三方包下载并解压到你的`GOPATH`路径下的`src文件夹`里面去,并执行`go install xxx`命令来安装该包,结果是在`GOPATH`路径的`pkg文件夹`生成`xxx.a`文件
实际上`go get`就是`git clone` + `go install`的组合
由上面可知, windows在调用`go get`之时使用到了`git`,所以必须先安装安装`git`
(2)手动安装:
先下载该包,并按照该包官方的下载路径 为该包创建对应的`gopath/src`下里面的路径,
注意这一步很关键!第三包在src里的路径不能随意放在一个文件夹中,因为第三方包内部的文件里还有对其它包的引用,如果随意放置会导致导入路径失效。
将包移入到该路径,执行`go install`命令安装这个文件
go.mod文件

go环境的一些修改
自动下载
go env -w GO111MODULE=on
设置环境为国内代理
go env -w GOPROXY=https://goproxy.cn,direct
内置函数make
内置函数make,是用来为slice,map或者chan这3种类型分配内存哈初始化一个对象的。
注意:make只能用在这3种类型上。
package main
func main() {
var slice_1 []int = make([]int, 5, 10)
fmt.Println(slice_1)
var slice_2 []int = make([]int, 5)
fmt.Println(slice_2)
}
func main() {
var map1 map[string]int = make(map[string]int)
map1["one"] = 1
fmt.Println(map1)
var map2 map[string]int = map[string]int{"1":1}
map["2"] = 2
fmt.Println(map2)
}
如何获取一个整数的各个位上的数字
package main
import "fmt"
func main() {
var temp_data int = 123
fmt.Println(temp_data/100%10)
fmt.Println(temp_data/10%10)
fmt.Println(temp_data/1%10)
}
go语言中的算数运算符号/关系运算符/逻辑运算符/位运算符
GO语言中,有很多值得学习的运算符,最基本的就是算数运算符,就是加减乘除取余,然而还有其它的有意思的运算符哦,一起来看看吧,注释写的很详细哦。
package main
import "fmt"
func main() {
a := 10
b := 20
fmt.Println(a + b)
fmt.Println(a - b)
fmt.Println(a*b, a/b, a%b)
a++
b++
fmt.Println(a)
fmt.Println(b)
fmt.Println(a == b, a >= b, a <= b, a != b)
fmt.Println(10 > 5 && 5 > 2)
fmt.Println(10 > 4 || 5 > 6)
fmt.Println(!(10 > 5))
aa := 1
bb := 5
fmt.Println(aa & bb)
fmt.Println(aa | bb)
fmt.Println(aa ^ bb)
fmt.Println(1 << 2)
fmt.Println(4 >> 2)
}
判定空值
<1> "" 空字符串
var test string
if test == "" {
fmt.Println("test is empty")
}
<2>nil
nil一般是判断结构体的指针是否为空
type test struct {
name string
password string
}
func main() {
var data *test
if data == nil {
fmt.Println(" struct data is empty)
}
}
<3> len(x) == 0
func main() {
var test []string
if len(test) == 0 {
fmt.Println("[]string test is empty")
}
}
go中的全局变量和局部变量
在golang中,全局变量的生命周期属于整个包,这个和C不同,因为C语言没有包的概念。
在golang的main包中,main包定义的全局变量无法被其他包引用。
如果想使用全局变量,建议在其他包中定义并进行引用。
在golang中,局部变量的生命周期属于花括号{}之内,这和C语言一致。
还有,在声明了一个全局变量之后,如果再声明一个同名的局部变量,该同名局部变量的生命周期为花括号{}内。
在其他语言中,局部变量会得到明显确认,但golang中,有种声明局部变量的语法糖 := 。
如下面例子:
var p int
func test(i int) (int, error) {
return i + 1, nil
}
func main() {
p, err := test(4)
if err != nil {
log.Fatal(err)
}
}
结构体的定义 && 结构体变量
结构体和结构体变量的区别和联系
1 结构体是自定义的一种数据类型,代表一类事物。
2 结构体变量(实例)是具体的,实际的,代表一个具体变量。
以上的解释,其实我们可以理解为结构体就像是python中的类class,
而结构体变量就是我们根据这个类class,而实例出来的一个实例化对象。
我们看一个根据这个结构体(类class),实例出无数个对象。
如何自定义一个结构体
基本语法是:
type 结构体名称 struct {
field1 type
field2 type
field3 type
.... ....
}
结构体中的field的数量是没有限制的
demo:
type Student struct {
Name string
Age int
Score float32
}
以上我们自定义了一个Student的结构体(或者称为一个类)
可以看到,结构体的名称和field的名称,首字母都是大写的。
而且行与行之间是没有逗号分隔的。
field/字段/属性
从概念上来说,结构体字段=属性=field
字段是结构体的一个组成部分,一般是基本数据类型/数组,也可以是引用类型。
根据一个结构体创建一个结构体变量的时候(也就是实例化一个对象),如果没有给field赋值,则会对应一个初始值。
字符串的初始值是“”,int的初始值是0,float的初始值是0.0,
指针,slice map的初始值都是nil,及还没分配空间。
实战demo
package main
import "fmt"
type Person strct {
Name string
Age int
Scores [5]float64
ptr *int
slice []int
map1 map[string]string
}
func main() {
var p1 Person
fmt.Println(p1)
if p1.ptr == nil {
fmt.Println("ok1")
}
if p1.slice == nil {
fmt.Println("ok2")
}
if p1.map1 == nil {
fmt.Println("ok3")
}
p1.slice = make([]int, 10)
p1.slice[0] = 100
p1.map1 = make(map[string]string)
p1.map1["key1"] = "tom~"
fmt.Println(p1)
}
{ 0 [0 0 0 0 0] <nil> [] map[]}
ok1
ok2
ok3
{ 0 [0 0 0 0 0] <nil> [100 0 0 0 0 0 0 0 0 0] map[key1:tom~]}
不同的结构体变量的字段field是独立的,互不影响,一个结构体变量字段的更改,不会影响另一个结构体变量
package main
import "fmt"
type Monster struct{
Name string
Age int
}
func main() {
var monster1 Monster
monster1.Name = "牛魔王"
monster1.Age = 500
monster2 := monster1
monster2.Name = "青牛精"
fmt.Println("monster1=", monster1)
fmt.Println("monster2=", monster2)
}
go语言中的切片slice
关于对slice的操作,主要有以下几种操作
输出slice中指定位置(这里的位置类似于python中的index,都是从0开始)的元素。
遍历切片中的原素,输出index和元素。
复制切片
修改切片中的元素
在切片中添加元素
用for循环打印整个元素
package main
import "fmt"
func main() {
var food = []string{"苹果", "橘子", "香蕉", "西瓜", "大鸭梨"}
fmt.Println(food[1])
for id, name := range food {
fmt.Println(id)
fmt.Println(name)
}
var food2 = food[:]
fmt.Println(food2)
food3 := make([]string, 6)
copy(food3, food2)
fmt.Println(food3)
food3[0] = "哈密瓜"
fmt.Println(food3)
food = append(food, "大西红柿")
fmt.Println(food)
fmt.Println(food[:3])
for _, name := range food {
fmt.Println(name)
}
}
go打印变量的类型
