[Golang]基础知识

变量声明

1.单个变量声明 var name string 这样声明一个变量,注意如果没有赋初始值,那么字符串初始值为空字符串“”,int为0,float为0.0,bool为false,指针类型为nil。

在go中,单引号和双引号有区别。在初始化变量时,如果右值带有小数点,那么建议带上类型float32。

2.多个变量一起声明,声明多个变量

1
2
3
4
5
var (
old_name string
age int
gender float32
)

3.匿名变量的优点

  • 不分配内存,不占用内存空间
  • 不需要你为命名无用的变量名而纠结
  • 多次声明不会有任何问题

整型

upload successful
在go中最好不要直接使用int给变量作为type,原因在于在32位机器上,int表示4个字节相当于int32,在64位机器上,int 表示8个字节,相当于int64。

二进制表示一个数:0b110
八进制表示一个数: 0o14
十六进制表示一个数:0xC

fmt格式化代码:

1
2
3
4
5
6
7
8
9
%b 格式化为二进制,
%c unicode码值
%d 十进制
%o 八进制
%x 十六进制
%X 十六进制
%U unicode格式
%E 科学计数法
%f 浮点数格式

浮点型

浮点数类型的值一般由整数部分、小数点“.”和小数部分组成。

其中,整数部分和小数部分均由10进制表示法表示。不过还有另一种表示方法。那就是在其中加入指数部分。指数部分由“E”或“e”以及一个带正负号的10进制数组成。比如,3.7E-2表示浮点数0.037。又比如,3.7E+1表示浮点数37。

有一点需要注意,在Go语言里,浮点数的相关部分只能由10进制表示法表示,而不能由8进制表示法或16进制表示法表示。比如,03.7表示的一定是浮点数3.7。

float32 和 float64

Go语言中提供了两种精度的浮点数 float32 和 float64。

float32,也即我们常说的单精度,存储占用4个字节,也即4*8=32位,其中1位用来符号,8位用来指数,剩下的23位表示尾数。

upload successful

float64,也即我们熟悉的双精度,存储占用8个字节,也即8*8=64位,其中1位用来符号,11位用来指数,剩下的52位表示尾数。

upload successful

浮点数类型的取值范围可以从很微小到很巨大。浮点数取值范围的极限值可以在 math 包中找到:

  • 常量 math.MaxFloat32 表示 float32 能取到的最大数值,大约是 3.4e38;
  • 常量 math.MaxFloat64 表示 float64 能取到的最大数值,大约是 1.8e308;
  • float32 和 float64 能表示的最小值分别为 1.4e-45 和 4.9e-324。

注意浮点数表示精度的问题:

  1. float32的精度只能提供大约6个十进制数(表示后科学计数法后,小数点后6位)的精度

  2. float64的精度能提供大约15个十进制数(表示后科学计数法后,小数点后15位)的精度

byte和rune

byte用来表示一个ASCII码字符,rune占有四个字节,表示一个unicode字符。

单引号用来表示字符,如果你使用双引号,就意味着你要定义一个字符串,赋值时与前面声明的前面会不一致,这样在编译的时候就会出错。

byte 和 uint8 没有区别,rune 和 uint32 没有区别,那为什么还要多出一个 byte 和 rune 类型呢?

理由很简单,因为uint8 和 uint32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。

字符串

字符串一般用双引号表示””,但是字符串也可以用``反引号,在反引号中,会忽略转义字符。

数组与切片

数组是一个由固定长度的特定元素类型组成的序列。

注意:

  1. [3]int 与[4]int是不同的数据类型
  2. 如果在声明数组时,不想声明容量大小,可以使用name := [...]int{}类型的方式来让go自动识别大小。
  3. 可以给自定义的数组类型重命名,使用type关键字:
1
2
type arr [3]int
var name arr = arr {1,2,3}

数组 与 切片 有相同点,它们都是可以容纳若干类型相同的元素的容器

也有不同点,数组的容器大小固定,而切片本身是引用类型,它更像是 Python 中的 list ,我们可以对它 append 进行元素的添加。

取切片值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
m := make([]int, 2, 10)
fmt.Println(m)

fmt.Printf("\n")
myarr := []int{}
fmt.Println(myarr)
myarr = append(myarr, 2)
fmt.Println(myarr)
myarr = append(myarr, []int{7, 8, 9}...) //解包切片
fmt.Println(myarr)
myarr = append([]int{100}, myarr...) //在第一个位置插入
fmt.Println(myarr)
fmt.Println(myarr[len(myarr)-1])
myarr = append(myarr[0:len(arr)-1], append([]int{520, 520}, myarr[len(myarr)-1:]...)...) //在最后一个元素之前插入元素
fmt.Println(myarr)

字典与布尔类型

字典

字典的下标读取可以返回两个值,使用第二个返回值都表示对应的 key 是否存在,若存在ok为true,若不存在,则ok为false

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//********************************************
var socres map[string]int = map[string]int{"english": 92, "chinese": 85}
fmt.Println(socres)
users := make(map[string]int) //初始化一个字典
fmt.Println(users)
users["Echor"] = 19 //添加元素
users["zhou"] = 20
fmt.Println(users)
users["zhou"] = 21 //添加重复键元素
fmt.Println(users)
fmt.Println(users["zhou"]) //得到存在元素
_, ok := users["sss"]
fmt.Println(ok) //得到不存在元素
delete(users, "zhou") //删除存在元素
fmt.Println(users)
delete(users, "sss") //删除不存在元素
fmt.Println(users)
fmt.Println(users)
for k, v := range socres { //循环得到键值对
fmt.Println(k, v)
}

布尔类型

关于布尔值,无非就两个值:true 和 false。只是这两个值,在不同的语言里可能不同。

而在 Go 中,真值用 true 表示,不但不与 1 相等,并且更加严格,不同类型无法进行比较,而假值用 false 表示,同样与 0 无法比较。

指针

指针的概念学了c语言将不难理解,变量分为普通变量和指针变量;

流程控制

if-else if- else 判断

在golang中if-else if -else有以下特点:

  1. 在if之后可以接一个表达式
  2. }else{  }else if{必须和左右括号在同一行

switch-case

注意:

  1. 在case后面可以接多个判断条件,他们的关系是”或“;
  2. 可以使用fallthrough进行穿透,但是只能穿透一层;
  3. 当条件都不匹配时,匹配default

for循环

for 循环的基本模型

1
2
3
4
for [condition |  ( init; condition; increment ) | Range]
{
statement(s);
}

注意:

  1. 在go中没有while,通过for{}(在for后面不加任何表达式来控制无线循环)
  2. for range遍历可以可迭代对象。for range的for后面不能添加任何表达式

goto

不建议使用,使用方法如下:

1
2
3
4
5
goto flag:
****
flag:
****
****

defer语句

  1. 延迟调用。defer 的用法很简单,只要在后面跟一个函数的调用,就能实现将这个 xxx 函数的调用延迟到当前函数执行完后再执行。
  2. 多个defer满足”先进后出“的条件