6. Go 数据类型注意事项

数组

数组比较

  1. 数组比较时,首先比较数组长度
  2. 如果数组长度相同并且每个元素都相同,则两个数组相等
  3. 不同数据类型的数组比较会报编译错误

数组作为参数

  • 数组作为参数传递时会复制整个数组
  • 函数内对数组的操作都是针对复制体
  • 传递大数组时效率较低
  • 可以通过指针传递数组以提高效率
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 使用指针传递数组
func zero(ptr *[32]byte) {
    *ptr = [32]byte{}
}

// 使用示例
func main() {
    var arr [32]byte
    zero(&arr)
}

切片

切片特性

  1. 切片是对数组的引用
  2. 切片可以动态增长
  3. 切片作为参数传递时只传递引用

切片操作

1
2
3
4
5
6
7
8
// 创建切片
s := make([]int, 5, 10)  // 长度为5,容量为10的切片

// 追加元素
s = append(s, 1, 2, 3)

// 截取切片
s1 := s[1:3]  // 包含索引1,不包含索引3

Map

Map 特性

  1. Map 是引用类型,零值为 nil
  2. Map 不是并发安全的,需要加锁保护
  3. Map 的键必须是可比较的类型
  4. Map 的迭代顺序是随机的

Map 操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// 创建 map
m := make(map[string]int)

// 添加或更新键值对
m["key"] = 1

// 删除键值对
delete(m, "key")

// 检查键是否存在
if value, ok := m["key"]; ok {
    fmt.Printf("值: %d\n", value)
}

// 并发安全的 map
var syncMap sync.Map
syncMap.Store("key", 1)
value, _ := syncMap.Load("key")

Channel

Channel 特性

  1. Channel 是引用类型,零值为 nil
  2. Channel 必须使用 make 创建
  3. Channel 可以是有缓冲或无缓冲的
  4. 关闭后的 channel 仍然可以读取数据

Channel 操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 创建无缓冲 channel
ch := make(chan int)

// 创建有缓冲 channel
ch := make(chan int, 10)

// 发送数据
ch <- 1

// 接收数据
value := <-ch

// 关闭 channel
close(ch)

// 遍历 channel
for v := range ch {
    fmt.Println(v)
}

指针

指针特性

  1. 指针可以指向任何类型的变量
  2. 指针的零值是 nil
  3. 指针可以用于修改原变量的值

指针使用

1
2
3
4
5
// 指针声明和使用
var p *int
i := 42
p = &i
*p = 21  // 通过指针修改值

结构体

结构体特性

  1. 结构体字段可以导出(首字母大写)
  2. 结构体可以嵌入其他结构体
  3. 结构体可以实现接口

结构体示例

1
2
3
4
5
6
7
8
9
type Person struct {
    Name string
    Age  int
}

// 结构体方法
func (p *Person) SetAge(age int) {
    p.Age = age
}

接口

接口特性

  1. 接口是隐式实现的
  2. 接口可以组合
  3. 空接口可以存储任何类型的值

接口示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type Reader interface {
    Read(p []byte) (n int, err error)
}

type Writer interface {
    Write(p []byte) (n int, err error)
}

// 接口组合
type ReadWriter interface {
    Reader
    Writer
}

参考资源

57.12k 字
43篇文章