安装
https://golang.google.cn/dl/ 官网直接安装go。
打开cmd 输入 go version
然后安装ide,这边使用的是goland。
安装包和破解文件都在里面:直接安装,然后将jetbrains-agent-latest.zip拖到goland窗口,重启即可。
https://pan.baidu.com/s/1eyKoegOhHppqTxtNbHunpQ
w1m2
特性
1 | package main |
入门代码:输出一个ok
go有如下规则:
- 每个源文件都有一个专门的package
- 程序的入口依旧是main函数
- main函数必须在main 这个package下。
- 文件名称和package没有直接联系
- 可以 go run这个go文件,也可以go build这个模块后,生成对应的可执行的机器文件,直接执行。
变量
Go语言是静态强类型语言,所以变量是有明确类型的。
1 | var age string //声明 未赋值默认为0 |
可以声明其类型,然后赋值
1 | var name = "王钢蛋" |
也可以直接赋值。
Go语言支持根据数据推导数据类型的方法。所以在定义的时候可以不用写数据类型,直接根据你所初始化的值,来推导出定义的数据类型。
- 变量在使用前必须先声明。
- 变量名不能重复定义。
- 如果是简短定义方式,左边至少有一个是新的变量。
- 如果定义了变量,必须得使用,否则编译无法通过。
- 全局变量可以不使用也能编译通过,定义的全局变量和局部变量名称如果相同,则会优先使用局部变量。
- 简短定义方式不能定义全局变量,也就是不能声明在函数外部
常量
1 | const name = 111 |
由var变成了const
- 常量数值不能修改。
- 常量定义后可以不使用。
- 常量定义不能使用简短定义方式。
- 常量中使用的数据类型只能是 整型、布尔、浮点、复数类型、字符串类型。
iota是常量里面的计数器,初始值默认值是0,可以被编译器自动修改,每定义一组常量时,iota逐行自增1。
1 | const( |
输出
1 | 1 |
可以看到iota从0开始,每多一个变量,数字加一。每个常量都有这个属性。可以用其做一些骚操作。
如果下面没有声明常量的值,那么就和上面常量保持一致,如果第一行没有声明,那么报错。
数据类型
数据类型是一门高级语言的基础,Go属于又属于强类型静态编译语言。Go语言拥有两大数据类型,基本数据类型和复合数据类型。
整型
数据类型 | 说明 | 取值范围 |
---|---|---|
有符号整数 | ||
int8 | 有符号 8位整数 | -128到 127 |
int16 | 有符号 16位整数 | -32768 到32767 |
int32 | 有符号 32位整数 | -2147483648到2147483647 |
int64 | 有符号 64位整数 | -9223372036854775808到9223372036854775807 |
无符号整数 | ||
uint8 | 无符号8位整数 | 0到255 |
uint16 | 无符号16位整数 | 0到65535 |
uint32 | 无符号32位整数 | 0到4294967295 |
uint64 | 无符号64位整数 | 0到18446744073709551615 |
在Go语言中 byte与uint8 是一样的,rune与int32是一样的,代表同一种数据类型。但是int和int64 不是同一种类型。
int不等于上面任意一个类型。
Go语言中int类型的大小与具体的平台有关系,一般来说,int在32位系统中是4字节,在64位系统中是8字节,使用简短定义自动推导类型初始化一个整数,默认为int类型。
字符串:
字符串的概念就是多个byte的集合,一个字符序列用双引号””,或者`` (esc下面的键) 表示。
浮点数
Go语言有两种精度的浮点数 float32 和 float64。浮点类型的数据取值范围可以从很小或者很巨大。
单精度 浮点类型 | 取值范围 | |
---|---|---|
float32 | 负数时 | -3.402823E38 到 -1.401298E-45 |
float32 | 正数时 | 1.401298E-45 到 3.402823E38 |
双精度 浮点类型 | 取值范围 |
---|---|
float64 | -1.79E+308 到 +1.79E+308 |
1.79E-308
是 1.79 乘以 10的负308次方。 1.79E+308
是 1.79 乘以 10的308次方。
单精度双精度两者区别
在内存中占有的字节数不同
- 单精度浮点数在机内占4个字节。
- 双精度浮点数在机内占8个字节。
有效数字位数不同
- 单精度浮点数 有效数字7位。
- 双精度浮点数 有效数字16位。
对于float型数据,其长度是4个字节,右边23位用来表示小数点后面的数字,中间8位用来表示e,左边一位用来表示正负。
对于double型数据,其长度是8个字节,右边52位用来表示小数点后面的数字.中间11位表示e,左边一位用来表示正负。
数据类型转换
go 语言是静态语言,要求,定义、赋值、 运算、类型一致才能进行操作。所以要进行操作的时候必须保证数据类型一直。需要注意的是,只有兼容的数据类型才能够转换。 强制类型转换的语法 Type(value)
1 | var a1 int=10 |
运算符
这个和java差不多,没啥区别。主要说几个没玩过的
- &^ : a&^b 对于b上面的每个数值,如果为0,则去a上的数值,如果为1,则是0(很有趣不知道有什么用)
- ^ :异或,不解释。
- <<,>> 左移和右移,包含符号位的移动
赋值运算符
这块go是蛮有意思的了。
运算符 | 描述 |
---|---|
= | 把等号右侧的数值 赋给左边的变量 |
+= | 自身加上后面的值 再赋给左边的变量 |
-= | 自身减去后面的值 在赋给左边 |
/= | 自身除后面的值 再赋值给左边 |
%= | 自身与后面的值求余数后 再赋值给左边 |
<<= | 左移后再赋值 |
>>= | 右移后再赋值 |
&= | 按位与后再赋值 |
!= | 按位或 后再赋值 |
^= | 按位异或后再赋值 |
这块赋值操作,让代码节省了很多,有趣。
流程控制
if模块
这个和java的语法没有区别。
1 | if a3==a1{ |
但是go存在特殊的一些写法。条件判断之间再加上一段执行语句,执行的结果再用作后面的条件判断。例如
1 | if a4=a3; a3==a1{ |
试了一下,只能加一个语句哈。
switch模块
1 | //switch语法一 |
看看例子
1 | var sd="asds" |
在switch 语句中,默认每个case后自带一个break,表示到此结束 不向下执行了,跳出整个switch。fallthrough 表示强制执行后面的没有执行的下一个case代码。
for
语法: for init; condition;post{ }
init 初始化 只执行一次
condition bool类型 执行条件 如果满足继续执行后面的循环体 如果不满足 则终止执行
{} 循环体
- post 表达式 将在循环体执行结束之后执行
1 | for i:=0;i<3;i++{ |
break默认是结束当前循环,如果当前多重循环,那么可以如下:
1 | flag: |
给循环体加个标签,然后break掉。
goto模块
1 | Test: |
给语句加个标签,然后goto到那里直接执行。
复合数据类型
数组声明的语法格式为: var 数组名称 [长度]数据类型
- 数组只能用来存储一组相同类型的数据结构。
- 数组需要通过下标来访问,并且有长度和容量 。
1 | var sd [5] int |
数组不足补0处理。
数组的遍历,除了上面说的for,还可以
1 | for index,value:=range arr1{ |
slice
1 | var slice [] int |
通过make函数定义slice,然后通过append扩容进去。前面的3是长度,后面的8是容量,扩容时基于容量计算的。容量就是真实的数组长度,而长度则是当前slice元素数目。
除了用make创建slice,还可以通过new创建。但是不一样,看看效果。
1 | slice1 := new([]int) |
如果实现了扩容, 地址就会发生改变成新的地址,旧的则自动销毁。
删除数据
1 | slice:=[]int{1,2,3,4,5,6} |
:n,表示获取这个slice前面n个元素,n:,表示获取获取第三个元素后面的其余元素。
1 | i := 2 // 要删除的下标为2 |
相当于删除了第i个元素,其逻辑是,获取前面2个元素,然后再把第三个元素后面的元素添加进去。
总结一下
- 每一个切片都引用了一个底层数组。
- 切片本身不能存储任何数据,都是这底层数组存储数据,所以修改切片的时候修改的是底层数组中的数据。
- 当切片添加数据时候,如果没有超过容量,直接进行添加,如果超出容量自动扩容成倍增长。
- 切片一旦扩容,指向一个新的底层数组内存地址也就随之改变。
- 声明了长度的就是数组,没有声明就是slice,快速定义模式的,如果是make声明长度的则是slice
- 数组,slice都是声明的变量,实际数据存储在内存。
map
和java里面的map一样,创建和删除语法如下:
1 | var map1 map[string]string |
遍历
1 | map1:=make(map[int]string) |
map在Go语言并发编程中,如果仅用于读取数据时候是安全的,但是在读写操作的时候是不安全的,在Go语言1.9版本后提供了一种并发安全的,sync.Map是Go语言提供的内置map,不同于基本的map,他提供了特有的方法,不需要初始化操作实现增删改查的操作。
1 | var syncmap sync.Map |