Skip to content

make

用于分配并初始化的工具。专门用来创建并初始化 slice、map、channel,返回值本身(不是指针)。针对于不同的类型帮用户在底层做一些事情

go
// slice:长度5,容量10(已初始化为零值)
orders := make([]string, 5, 10) 

// map:可以直接往里面塞东西
menu := make(map[string]float64)
menu["红烧肉"] = 38.5

// channel:无缓冲
ch := make(chan int)
// 有缓冲,容量3
bufferedCh := make(chan int, 3)

make 只用于这三种类型,别的类型用不了

new

分配一块内存,填上零值,返回指向它的指针*T

go
p := new(int)
// p 是 *int,指向 0
*p = 42

通常直接用 &T{} 更常见,比如 s := &Student{}new 基本只在很底层或特殊场合出现

append

向 slice(切片) 尾部追加元素,返回新的 slice(因为扩容换了底层数组)

go
dishes := []string{"红烧肉"}
dishes = append(dishes, "清蒸鱼", "西红柿炒蛋")
// dishes 现在是 ["红烧肉", "清蒸鱼", "西红柿炒蛋"]

扩容规则(大致):旧容量小于 256 时,扩容为原来的两倍左右;之后按一定比例增长,减少内存浪费

最佳实践

  • 一定要用变量接收返回值,append 返回新的 slice 头
  • 若预先知道大致元素数量,用 make([]T, 0, cap) 预分配容量,避免反复扩容

copy

把源 slice 的元素拷贝到目标 slice,返回实际拷贝的元素数(取两者最小长度)

go
src := []int{1, 2, 3, 4}
dst := make([]int, 2)
n := copy(dst, src)
// dst = [1, 2]; n = 2

一般用于深拷贝 slice 底层数据;不改变原 slice 的 capacity 情况下的安全复制

len&cap

len(v):求长度(slice 里现有多少数据,map 里多少键值对,channel 里缓冲了多少元素)

cap(v):求容量(slice 底层数组总长度,channel 的缓冲总格数)

go
s := make([]int, 3, 5)
fmt.Println(len(s)) // 3
fmt.Println(cap(s)) // 5

delete

从 map 中删除给定的键

go
menu := map[string]float64{"红烧肉": 38.5}
delete(menu, "红烧肉")

close

关闭一个 channel,表示不再发送数据

关闭后:

  • 接收方可以继续读取已缓冲的数据,读完后得到零值,okfalse
  • 往已关闭的 channel 发送数据会 panic
go
ch := make(chan int, 2)
ch <- 1
close(ch)
v, ok := <-ch  // 1, true
v, ok = <-ch   // 0, false