GO语言优缺点及基础语法 | 青训营

616 阅读13分钟

GO语言优缺点:

  • Go语言(也称为Golang)是一种由Google开发的编程语言,它具有许多优点,以下是Go语言的一些主要优点;
  1. 简洁易读: Go语言采用简洁的语法和清晰的代码结构,使得代码易于编写、阅读和维护。这有助于减少出错的可能性,并促进团队合作。
  2. 高效性能: Go语言具有出色的运行时性能,其编译器能够将代码优化为高效的机器代码。这使得Go适用于需要高性能的应用程序,如网络服务器、分布式系统等。
  3. 并发支持: Go语言内置了强大的并发支持,通过Goroutines和Channels来实现。Goroutines是轻量级的线程,能够高效地并行执行,而Channels用于在Goroutines之间进行通信和同步,使得编写并发代码变得更加容易。
  4. 垃圾回收: Go语言自带垃圾回收机制,可以自动管理内存,减轻了开发者的负担,同时避免了常见的内存泄漏和悬垂指针问题。
  5. 快速编译: Go语言的编译速度非常快,这有助于快速迭代和开发。代码修改后,只需短时间的编译即可查看结果。
  6. 静态类型: Go是一种静态类型语言,这意味着在编译时会进行严格的类型检查,可以在早期发现很多错误,减少运行时错误的可能性。
  7. 跨平台支持: Go语言支持多种操作系统和体系结构,因此可以轻松地在不同平台上部署和运行代码。
  8. 开发效率: 由于Go语言的简洁语法和丰富的标准库,开发者可以更快地完成项目。标准库提供了许多常用功能,不需要额外的第三方库。
  9. 良好的工具生态系统: Go语言拥有丰富的工具生态系统,包括强大的包管理工具(例如go getgo mod)、代码格式化工具(gofmt)、性能分析工具等。
  10. 适合分布式系统: Go语言的并发模型和网络库使其非常适合构建分布式系统和微服务架构,因为它可以轻松地处理高并发和并行性需求。
  • GO语言缺点:
  1. 相对年轻: 相对于一些其他编程语言,Go语言的历史较为短暂。这意味着它的生态系统和第三方库相对较小,可能缺少一些成熟的解决方案。
  2. 不支持泛型: 在截至目前的版本中,Go语言尚未原生支持泛型。这可能导致一些代码重复或在某些情况下不够灵活,虽然在未来的版本中可能会加入泛型支持。
  3. 错误处理: Go语言的错误处理机制基于返回值,需要在函数调用的每个地方显式检查错误。这可能导致代码中充斥着大量的错误检查代码,使得代码变得繁琐。
  4. 依赖管理: 尽管Go语言在依赖管理方面取得了一些进展,但在一些复杂的项目中,依赖管理仍然可能变得复杂,特别是在需要处理多个版本的库时。
  5. 缺乏一些高级特性: 与一些其他编程语言相比,Go语言在一些高级特性方面可能相对缺乏,例如函数式编程的支持和元编程等能力。
  6. 性能折衷: 虽然Go语言的性能相对较好,但在一些特定的应用场景下,如数值计算密集型任务,可能会受到其他语言(如C++)的优势。
  7. 不适合所有应用场景: 尽管Go语言在许多领域表现出色,但并不适合所有类型的应用场景。例如,如果项目需要特定的领域专业知识或复杂的数据处理,其他语言可能更合适。
  8. 社区支持有限: 虽然Go语言的社区在增长,但与某些其他主流语言相比,其社区支持可能相对有限,这可能会影响到解决问题和获取支持的速度。

GO语言基础语法:

  1. 变量定义: 在Go语言中,使用关键字 var 来声明变量,并通过赋值来初始化变量。变量名在前,类型在后 屏幕截图 2023-08-16 191310.png 也可以在声明变量的同时初始化: 屏幕截图 2023-08-16 191348.png 或者使用类型推断,省略类型: 屏幕截图 2023-08-16 191452.png 更简洁的方式是使用短变量声明 :=,这会根据右侧的值自动推断变量类型: 屏幕截图 2023-08-16 191533.png 2 . 常量定义: 使用关键字 const 来声明常量,并在声明时就必须进行初始化。 屏幕截图 2023-08-16 191652.png

  2. 数据类型: Go语言具有各种基本数据类型,例如整数、浮点数、字符串、布尔值等。

    • 整数类型:int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64
    • 浮点数类型:float32, float64
    • 字符串类型:string
    • 布尔类型:bool
  3. 类型转换: 类型转换需要显式指定类型。 屏幕截图 2023-08-16 191826.png 零值: 在声明变量但不进行初始化时,变量会被赋予其类型的零值。 屏幕截图 2023-08-16 191903.png 多重赋值: 可以同时给多个变量赋值。 屏幕截图 2023-08-16 191946.png 匿名变量: 使用下划线 _ 表示匿名变量,用于忽略某个值的赋值。 屏幕截图 2023-08-16 192024.png 常量枚举: 使用关键字 const 来创建一组常量枚举。 屏幕截图 2023-08-16 192104.png

2.if else语法:

在Go语言中,ifelse 是用于条件控制的关键字,用于根据条件的真假来执行不同的代码块。 屏幕截图 2023-08-16 192447.png 在这里,condition 是一个表达式,其结果为布尔值(truefalse)。如果 condition 的结果为 true,则执行 if 代码块,否则执行 else 代码块。 你也可以省略 else 部分,只使用 if,这将会执行一段代码,如果条件为真的话。 下面是一个使用 ifelse 的示例: 屏幕截图 2023-08-16 192539.png 在这个示例中,如果 age 大于等于 18,则打印出 "成年人",否则打印出 "未成年人"。 此外,你还可以在 if 语句中使用短变量声明: 屏幕截图 2023-08-16 192741.png 根据条件的不同,会执行不同的代码

3.循环语法:

for 循环: for 循环是最常用的循环结构,可以用于重复执行一段代码块,直到满足指定的条件。 屏幕截图 2023-08-16 193040.png 你也可以使用 for 来模拟 while 循环: 屏幕截图 2023-08-16 193110.png或者使用 for 来模拟无限循环: 屏幕截图 2023-08-16 193201.pngrange 循环: range 循环用于迭代数组、切片、映射等集合类型的元素。 屏幕截图 2023-08-16 193236.png Go语言中没有 while 循环,但你可以使用 for 循环来实现相同的功能。此外,Go语言还提供了 breakcontinue 语句用于在循环中控制流程,以及 fallthrough 语句用于在 switch 语句中控制流程。

4. switch语法:

在 Go 语言中,switch 语句用于根据一个表达式的值,从多个可能的情况中选择一个分支执行。以下是 switch 语句的基本语法: 屏幕截图 2023-08-16 193449.png每个 case 分支表示一个可能的值,expression 是要匹配的表达式。只有一个 case 分支会被执行,如果没有匹配的分支,则会执行 default 分支(如果有的话)。 屏幕截图 2023-08-16 193608.png 在这个示例中,根据 day 的值,选择一个相应的分支进行执行。

注意事项:

  • 每个 case 分支的值必须是唯一且可比较的。
  • case 分支的值可以是常量、变量、表达式等。
  • 在 Go 语言中,switch 语句自带了 break 效果,即一旦匹配到一个分支,就会执行对应的代码块并退出 switch 语句。如果需要继续执行后续分支,可以使用 fallthrough 关键字。

5.数组:

在 Go 语言中,数组是一种固定长度且类型相同的数据结构,用于存储一组相同类型的元素。数组在内存中是连续分配的,可以通过索引来访问数组中的元素。以下是创建和使用数组的基本语法: 屏幕截图 2023-08-16 193823.png

  • arrayName 是数组的名称。
  • length 是数组的长度,即元素的数量。
  • elementType 是数组中元素的数据类型。

以下是一个使用数组的示例: 屏幕截图 2023-08-16 193904.png注意:

  • 数组的索引从 0 开始。
  • 如果没有给数组元素赋值,默认会使用元素类型的零值。
  • 数组长度是数组类型的一部分,不同长度的数组是不同的类型,因此 [5]int[10]int 是不同的类型。

数组在一些场景中可能有限制,例如长度固定、不够灵活等。在实际开发中,切片(Slice)更常用,因为切片具有动态长度,更加方便灵活。

6.切片:

在 Go 语言中,切片(Slice)是一种动态长度的数据结构,它可以用来存储一系列相同类型的元素,并且可以根据需要动态增加或减少元素个数。切片是基于数组的封装,提供了更灵活和方便的数据操作方式 屏幕截图 2023-08-16 194112.png

  • sliceName 是切片的名称。
  • elementType 是切片中元素的数据类型。

切片是基于数组创建的,但与数组不同,切片没有固定长度。切片可以通过指定下标范围来访问数组的一部分。 以下是一个使用切片的示例: 屏幕截图 2023-08-16 194219.png 注意:

  • 切片的长度是切片中实际存储的元素个数。
  • 切片的容量是从创建切片的索引位置到底层数组的末尾的元素个数。当切片的长度超过容量时,会自动重新分配底层数组,使其容量变大。
  • 使用 append 函数可以向切片添加元素。
  • 切片可以通过切片表达式 a[start:end] 来截取子切片。

由于切片具有动态长度和灵活性,它在实际编程中使用非常广泛,特别适合处理动态数据集合。

7.map语法:

map 是一种无序的键值对集合,也称为字典(Dictionary)或关联数组。每个键只能对应一个值,键必须是唯一的,但值可以重复。map 提供了一种通过键来快速检索和访问值的方式。 屏幕截图 2023-08-16 194501.png

  • mapNamemap 的名称。
  • keyType 是键的数据类型。
  • valueType 是值的数据类型。 以下是一个使用 map 的示例: 屏幕截图 2023-08-16 194557.png 注意:
  • 使用 make 函数创建一个空的 map
  • 使用方括号 [] 来访问 map 中的元素,键的类型在方括号中。
  • 使用 delete 函数来删除 map 中的元素。
  • 使用 _, ok 来判断键是否存在,如果存在,oktrue,否则为 falsemap 在实际开发中经常用于存储键值对,例如存储配置信息、缓存数据、数据库记录等。由于 map 是无序的,遍历 map 的顺序是不确定的。如果需要有序遍历键值对,可以将键排序后再遍历。

8.range语法:

range 关键字用于遍历各种数据结构,如数组、切片、映射、字符串等。它提供了一种简便的方式来遍历数据集合的元素。使用 range,你可以在循环中逐个获取数据集合中的元素和索引。 屏幕截图 2023-08-16 194813.png

  • collection 是要遍历的数据集合,可以是数组、切片、映射、字符串等。
  • index 是当前元素的索引(可选)。
  • value 是当前元素的值。

以下是一些使用 range 的示例:

  1. 遍历切片: 屏幕截图 2023-08-16 194854.png遍历映射: 屏幕截图 2023-08-16 194930.png遍历字符串: 屏幕截图 2023-08-16 195006.png需要注意的是,当遍历字符串时,range 返回的索引是字符在 UTF-8 编码中的字节位置,而不是字符的实际位置。

使用 range 可以方便地遍历各种数据结构,而无需手动管理索引。它在循环处理数据时非常有用,并且能够有效减少编程错误。

9.函数语法:

函数是一种独立的代码块,用于封装一组操作或功能。函数可以被调用并传递参数,可以返回一个或多个值。 屏幕截图 2023-08-16 195206.png

  • functionName 是函数的名称。

  • parameters 是函数的参数列表,包括参数名称和类型。

  • returnType 是函数的返回值类型。

  • value 是函数的返回值(可选)。 以下是一个使用函数的示例: 屏幕截图 2023-08-16 195240.png注意:

  • 函数名称遵循标识符命名规则,使用驼峰式命名(例如 calculateSum)。

  • 函数可以有多个参数,参数之间用逗号分隔。

  • 函数可以有一个或多个返回值。如果没有返回值,可以省略 returnType

  • 函数体中的操作可以包含任何合法的 Go 语句。

  • 在调用函数时,需要传递参数,参数的顺序和类型必须与函数声明一致。 另外,Go 语言还支持多返回值的函数,你可以在函数的返回值列表中指定多个返回值,以逗号分隔。例如: 屏幕截图 2023-08-16 195313.png

10.指针语法:

指针是一种特殊的数据类型,用于存储变量的内存地址。通过指针,你可以直接访问变量的内存位置,以及对其进行操作。指针在函数参数传递、动态内存分配等方面非常有用。 屏幕截图 2023-08-16 195559.png variableType 是指针变量的数据类型,与指向的变量类型相同。 屏幕截图 2023-08-16 195630.png 在上面的示例中,我们创建了一个整数变量 num,然后声明了一个整数指针 ptr,将其指向 num 变量的内存地址。通过 *ptr 可以访问该地址处的值,也就是 num 的值。通过修改 *ptr 的值,我们也修改了 num 的值。 在函数中传递指针作为参数,可以实现在函数内部修改原始变量的值。例如: 屏幕截图 2023-08-16 195709.png在函数调用中,我们传递了变量的指针作为参数,并在函数内部使用指针来修改变量的值,这样可以影响到函数外部的变量。 需要注意的是,在 Go 语言中不存在指针运算(如 C/C++ 中的指针加减操作),并且指针可以为 nil,表示不指向任何内存地址。指针在某些情况下可能会带来内存安全问题,因此在使用指针时要小心,并确保不会访问无效的内存地址

11.结构体语法:

结构体(Struct)是一种用户自定义的复合数据类型,用于将不同类型的字段(成员)组合在一起,以表示一个完整的实体。结构体可以包含不同类型的字段,这使得它非常适合表示真实世界中的复杂数据结构。 屏幕截图 2023-08-16 200110.png

  • StructName 是结构体的名称。
  • Field1, Field2, ... 是结构体的字段名。
  • type1, type2, ... 是字段的数据类型。 以下是一个使用结构体的示例: 屏幕截图 2023-08-16 200154.png你还可以使用结构体字面值来创建结构体实例: 屏幕截图 2023-08-16 200246.png结构体实例的字段可以通过点运算符(.)来访问和修改。与指针类似,你可以将结构体作为函数参数传递,以便在函数内部修改结构体的值。结构体还可以嵌套在其他结构体中,以表示更复杂的数据关系。

结构体在面向对象编程中扮演着重要角色,可以用来构建自定义数据类型,管理数据和行为。