1392 字
7 分钟
Golang的知识碎片(基础篇)
2025-09-14

Golang的知识碎片#

在此之前golang单纯看蓝山的文档,感觉学的很浅很零碎,所以打算重新看一遍。因为go by example、tour go和蓝山工作室的文档比较完善,所以下方将着重提及一些之前不太清楚的零碎知识,提醒自己。

0.Go 语言的零值机制

在 Go 语言中,所有变量在声明时都会被自动初始化为其类型的零值(zero value):

  • 数值类型:0
  • 布尔类型:false
  • 字符串类型:""(空字符串)
  • 指针、接口、切片、映射、通道:nil
  • 结构体:每个字段都初始化为其类型的零值

1.变量声明

关于变量的声明包括两部分,类型和初始值,变量会从初始值中推断出类型或从类型中推断出初始值(即零值)

2.返回值

Go 的返回值可以被命名(向前面的参数一样),return后面没有参数,就会返回没有命名的返回值

3.条件语句前简短语句

for和if 语句可以在条件表达式前执行一个简短语句

4.无条件的switch(类似于if-else)

switch {
case x < 0:
fmt.Println("Negative")
case x == 0:
fmt.Println("Zero")
default:
fmt.Println("Positive")
}

5.defer推迟/defer栈

  • defer 语句会将函数调用推迟到外层函数返回之后执行
  • 被推迟的函数调用会被压入一个中,当外层函数返回时,被推迟的函数会按照后进先出(LIFO)的顺序执行

6.函数闭包

闭包 = 函数 + 外部变量变量

  1. 状态保持:闭包可以记住并修改外部变量
  2. 独立实例:每次调用外部函数都会创建新的闭包实例
  3. 实用性强:用于需要保持状态的场景

如何判断外部变量

  1. “这个变量是在内层函数内部定义的,还是外部定义的?”
  2. 再问:“内层函数是否使用了这个外部变量?”
  3. 如果两个答案都是”是”:那么这个变量就是被捕获的外部变量

7.方法

方法可以看作有接收者的函数,不过带指针/值参数的函数必须接受一个指针/值,不然会报错,而以指针/值为接收者的方法被调用时,接收者既能为值又能为指针,不过能不能生效另说

8.接收者类型

接收者有两种类型,值接收者指针接收者

使用指针接收者的两个原因:

1.方法需要修改接收者的值,值接收者只能改变副本,指针可以改变原始值

2.提高效率,每次方法调用时,Go 需要将整个结构体的数据复制一份给方法使用。如果结构体非常大,这个复制操作的开销会很大。而Go 只需要复制一个指针(通常是一个机器字长的大小,如 8 字节),开销极小。

所以,大部分的时候使用指针

tips

对于一个特定的类型,你应该决定是使用值接收者还是指针接收者,并为该类型的所有方法保持一致

9.值类型/引用类型

这是 Go 语言中一个非常重要的概念,决定了变量如何被分配内存、如何被赋值以及如何被传递给函数。

值类型 (Value Types)#

  • 包括: 所有基本数据类型(如 int, float64, bool, string)、数组(Array)、结构体(struct)。
  • 行为特点:
    1. 变量直接存储值本身。
    2. 赋值操作和函数传参时,会创建值的完整副本。 修改副本不会影响原始值。
    3. 在内存中,通常被分配在栈(Stack) 上(但编译器也可能决定分配在堆上)。
// 值类型示例:数组
arr1 := [3]int{1, 2, 3}
arr2 := arr1 // 将 arr1 的【所有值】完整地复制一份给 arr2
arr2[0] = 100 // 修改副本
fmt.Println(arr1) // 输出: [1 2 3] (原值未改变)
fmt.Println(arr2) // 输出: [100 2 3]

引用类型 (Reference Types)#

  • 包括: 切片(Slice)、映射(Map)、通道(Channel)、指针(Pointer)、函数(Function)。
  • 行为特点:
    1. 变量存储的是一个“引用”(可以理解为内存地址),这个引用指向底层真正存储数据的内存空间。
    2. 赋值操作和函数传参时,复制的是这个“引用”(内存地址),而不是底层数据本身。 多个变量可以共享同一份底层数据。通过任何一个变量修改底层数据,其他所有引用它的变量都会“看到”这个变化。
    3. 底层数据通常存储在堆(Heap) 上。
// 引用类型示例:切片
slice1 := []int{1, 2, 3}
slice2 := slice1 // 复制的是引用(地址),现在 slice1 和 slice2 指向同一个底层数组
slice2[0] = 100 // 通过 slice2 修改底层数组
fmt.Println(slice1) // 输出: [100 2 3] (原值被改变了!)
fmt.Println(slice2) // 输出: [100 2 3]

总结对比表#

特性值类型引用类型
代表类型int, array, struct, stringslice, map, channel, pointer
变量存储内容实际的数据值指向底层数据的地址(引用)
赋值/传参行为复制整个数据值,创建独立副本复制引用地址,共享底层数据
修改副本的影响不影响原始数据影响原始数据
内存主要位置堆(数据本身),变量本身可能在栈

10.匿名函数/结构体…

暂时不太懂,标记一下

Golang的知识碎片(基础篇)
https://sheep44044.github.io/posts/技术/first-post/
作者
sheep44044
发布于
2025-09-14
许可协议
CC BY-NC-SA 4.0