Go语法基础 | 青训营笔记

139 阅读8分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

前言

大家好呀,这是我参加青训营伴学笔记创作活动的第 1 天,如存在问题,烦请各位斧正!

Go语言入门


Go的诞生

Go语言最初由Google公司的三个大牛于2007年开始设计发明,他们最终的目标是设计一种适应网络和多核时代的C语言。

1)从各种角度看,Go语言确实是从C语言继承了诸多编程思想。

2)但它舍弃了部分C的设计、重新设计了C语言中部分不太合理运算符的优先级,

  并在很多细微的地方都做了必要的打磨和改变。

Go能做什么

1)区块链研发

2)服务端: C相当它来讲,开发效率低、运维难度大。

  Go相当C有很大优化,并且Go语言据处理和大并发处理的能力非常突出。

3)游戏软件工程: 游戏数据通道会使用Go语言。

4)分布式/云计算软件: 如盛大云CDN、京东分布式文件系统。

Go的优点

1、高性能、高并发  |  2、语法简单、学习曲线平缓 |

3、丰富的标准库  |  4、完善的工具链 |

5、静态链接  |   6、快速编译 |

7、跨平台  |  8、垃圾回收 |

Go的开发环境

我个人是先安装了Goland,然后使用Goland安装了Go1.19。

具体版本各位自行选择,如有教程需要,可以自行搜索,不过多赘述。

Go与面向对象

1)面向对象:Go可以将函数绑定在结构体上;

2)面向过程:go的结构体不支持继承(但支持结构体的嵌套/组合)。

基本结构

func main(){         
  ...           
}

基本数据类型

基本分类

1)布尔型:布尔型的值只可以是常量 true 或者 false。

2)数字类型:整型 int 和浮点型 float等。

3)字符串类型:Go 的字符串是由单个字节连接起来的。

  Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。

4)派生类型:

  (1) 指针类型(Pointer)(2) 数组类型 (3) 结构化类型(struct) (4) Channel 类型

   (5) 函数类型 (6) 切片类型 (7) 接口类型(interface) (8) Map 类型

变量的声明

1、单个变量声明

1)标准声明方式:定义并赋值,注意类型是后置的: var a int = 2

2)推断声明方式:Go 支持变量类型自动推断,即赋值时可以省略类型信息:var a = 2(这种方式仅限定义时赋值的方式)

3)简短声明方式:定义时赋值的方式也可以通过":="符号来声明,比如: a := 2

2、批量声明

1)批量声明:多用于全局变量。举例:

var (   
  temp1 string   
  temp2 int
)

2)同类型批量声明,举例:var a,b int

3)批量简短声明,举例:a,b := 1,"string"

3、匿名变量

1)匿名变量不占用内存空间,不会分配内存,所以可以多次声明。

它的使用场景多为,为了忽略某些值,如下,为了让age拿到第二个返回值用到了匿名变量:

func foo() (string, int) {   
  return  "payne", 20
}
func main() {   
  _, age := foo()
}

4、常量

1)它的声明与变量的声明基本一致,将关键字var替换成了const。比如:consta int=1

基本类型

类型

描述

uint8 / uint16 / uint32 / uint64

无符号 8 / 16 / 32 / 64位整型

int8 / int16 / int32 / int64

有符号8 / 16 / 32 / 64位整型

float32 / float64

IEEE-754 32 / 64 位浮点型数

complex64 / complex128

32 / 64 位实数和虚数

byte/rune

类似 uint8 / int32,内置的两个字符类型

bool

uintptr

无符号整型,用于存放一个指针

指针

1)声明指针:var name *type

2)取地址符&:取出变量a的地址赋值给ip: ip =&a

3)零值:它属于引用类型,它的初始值为 nil。

4)取值:使用*指针名来取值。

数组

1、数组声明

Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:var name [SIZE] type(比如:varbalance [10]float32)

2、初始化数组

1)可以直接进行初始化:var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0} (若声明则指定值,依旧可以使用:=)

2)数组长度不确定:编译器通过元素个数自行推断数组长度,在[ ]中填入"..."。

3、go中数组名的意义:

1)C中数组名在本质上是数组中第一个元素的地址,但go中只表示整个数组。

2)所以在go中一个数组变量被赋值或者被传递的时候实际上就会复制整个数组。为了避免这种开销,往往需要传递一个指向数组的指针。

4、数组指针

1)存在数组a,则var ap = &a

2)除了避免传递数组时浪费空间,还可以用数组指针来foreach迭代:for i,v :=range b { ... }

结构体

结构体中可以定义多个不同的数据类型。

1、声明结构体

1)需要使用type和struct,type用于设定结构体的名称,struct用于定义一个新的数据类型。具体结构如下:

type 结构体名称 struct{    
  名称 类型 // 成员或属性   
  ...  
}

2)结构体可以定义在函数内部或函数外部(与普通变量一样),定义位置影响到结构体的访问范围

(1)如果结构体定义在函数外面,结构体名称首字母是否大写影响到结构体是否能跨包访问。

(2)如果结构体能跨包访问,属性首字母是否大写影响到属性是否跨包访问。

2、声明结构体变量

1)可以直接给结构体多个属性赋值:var peo People

// 按照结构体中属性的顺序进行赋值,可以省略属性名称

peo = People{"smallming", 17}

peo =People{Age:18, Name:"LiXC"}

2)通过结构体变量名称获取到属性进行赋值或查看值。

peo.Name="smallming"

fmt.Println(peo.Age)

3、结构体指针

由于结构体是值类型,在方法传递时希望传递结构体地址,可以使用时结构体指针完成。

1)可以直接声明结构体指针并赋值:

var peo *People

peo = &People{"smallming", 17}

2)可以结合new(T)函数创建结构体指针:peo := new(People)

3)使用结构体指针引用属性依旧可以只是用".",如:peo.Name = "smallming"

字符串

1、概述

1)Go 的字符串内部实现使用 UTF-8 编码,

2)Go 这样做的好处是① 减少内存和硬盘空间占用;② 不需要对使用 UTF-8 字符集的文本进行编码和解码。

3)Go 的字符串的值为双引号""中的内容。 而若是不想转义、即非解释型字符串,则使用反引号 str := `xxx`

4)Go 的字符串是一种值类型且值不可变,即字符串是字节的定长数组。

5)一般的比较运算符(==、!=、<、<=、>=、>)通过在内存中按字节比较来实现字符串的对比。

2、Go字符串底层

1)Go语言字符串本质是一个结构体,它的底层结构在reflect.StringHeader中定义,具体如下:

type StringHeader struct {    
  Data  uintptr   // 字符串指向的底层字节数组   
  Len  int   // 字符串的字节的长度。
}

2)Go语言的字符串中可以存放任意的二进制字节序列,而且即使是UTF8字符序列也可能会遇到坏的编码。

如果遇到一个错误的UTF8编码输入,将生成一个特别的Unicode字符‘\uFFFD’,显示为黑色菱形内部一个白色问号。

基本控制结构

选择语句

1、if-else语句

if 布尔表达式 {   
  ...
} else {   
  ...
}

1)在 Go 中,布尔表达式的括号是可选的,我们也建议不要使用括号。

2)但是大括号不可以省略,即使只有一条语句。

2、switch语句

1)其中的变量v可以是任何类型。val1和val2可以是同类型的任意值,类型不局限为常量或者整数,或者表达式(结果为相同类型)。

switch v {   
  case val1:       
    ...   
  case val2:       
    ...   
  default:       
    ...
}

2)甚至可以不写v,直接将val1等写为布尔类型表达式,就能代替多个if-else了。

3)要想跳转到下一个 case,可以在一整个case的末尾使用 fallthrough 关键字:(必须在末尾)

case 100:
    ... // 一些语句
    fallthroughcase 200:   
...

循环语句

go中只有for循环:

1)与普通for循环一样:for init; condition; post {}

2)与while循环一样:for condition{}

3)与for(;;)循环一样:for{}

4)迭代:for循环还可以直接使用range对slice、map、数组以及字符串等进行迭代循环,这之中也可以使用匿名变量来忽略一些值:

for _, value := range oldmap { }

控制语句

1)break:中断跳出循环或者switch语句

2)continue:跳过当前循环的剩余语句,然后继续下一轮循环