Golang Go语言中 append 追加问题

发布于 1周前 作者 nodeper 来自 Go语言

Golang Go语言中 append 追加问题

今天我在我的 1 核 2g 云服务器上处理 20 多万 excel 数据的时候直接把内存搞爆了!程序直接 kill 了! 其 1. 我没想到会有这么多数据,所以对 excel 读取后的处理没有分割处理,直接 apped 追加到一个新数组再分割数组分批次入库 其 2. 有些我在传递的时候是值传递。在 for 循环 append 直接追加的值。后面我改成了

//指针传递
a := append(a, &a)

但是我在分割数组的时候 append &报错 这个方法有何改进的呢

func SplitArr(data []interface{}, number int) [][]interface{} {
	//临时数据
	var temp [][]interface{}
	//统计有多少数据
	count := len(data)
	//每个子数组多少条数据
	pageNumber := number
	//分割数量
	page := int(math.Ceil(float64(count) / float64(pageNumber)))
	for i := 0; i < page; i++ {
		if i == page-1 {
			step := i * pageNumber
			temp = append(temp, data[step:])
		} else if i == 0 {
			temp = append(temp, data[i:pageNumber])
		} else {
			currentStep := i * pageNumber
			nextStep := currentStep + pageNumber
			temp = append(temp, data[currentStep:nextStep])
		}
	}
	return temp
}

还有问题想问

1.我在 for range 的时候不是指针追加 是不是循环的时候内存越增越大?? 2.不是指针传递 := 赋值是不是又开辟了一块新内存存的相同的值,却不同内存地址


更多关于Golang Go语言中 append 追加问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

12 回复

fatal error: runtime: out of memory 内存爆了 目前我 defer recover 也无法捕获到。还有什么办法捕获到吗?

更多关于Golang Go语言中 append 追加问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用 channel 试试?

append 每次是翻倍申请❤内存然后 copy 的吧,所以优化写法或者提前申请好空间

temp 换成 map 类型试试, page 作为 key 递增

可以用 pprof 看看哪里 malloc 了多少内存,立刻就能定位问题

append &报错是因为类型不匹配吧

var temp []*[]interface{}
然后
t := data[step:]
temp = append(temp, &t)

试下这样写之后内存是怎么分配的?

append 会重新申请空间的
而且 for range 是遍历对象的拷贝,这样子也会消耗空间。
如果你要处理量大的最好先预先分配

pandas 他不香吗😂

我直接 append(temp, &data[:]) 报了错 就没移出来 谢了!

谢了 找到这条技能了
谢谢,后面根据情况来预先分配

在Go语言中,append 函数用于向切片(slice)追加元素,是日常开发中非常常用的操作。然而,append 的行为有时可能会让初学者感到困惑,主要是因为切片在容量(capacity)不足时会自动扩容。

当向切片追加元素时,如果切片的当前容量足够容纳新元素,append 操作会直接在原切片的尾部添加元素,不会改变切片的底层数组。但如果当前容量不足,Go语言会分配一个更大的底层数组,并将原数组的元素复制到新数组中,然后再添加新元素。这个新的底层数组通常会比原数组大很多(通常是原容量的两倍),以减少未来扩容的次数。

需要注意的是,由于这种自动扩容机制,append 可能会返回一个新的切片(指向新的底层数组),原切片的引用将不会看到新添加的元素。因此,在链式调用append或在函数间传递切片时,需要特别注意这一点。

此外,如果向切片追加多个切片(例如append(slice1, slice2...)),append 会将slice2的所有元素依次追加到slice1的末尾。

总之,在使用append时,要意识到它可能改变切片的底层数组,并可能返回一个新的切片引用。在处理切片时,特别是在并发环境中,需要谨慎处理这些潜在的变化,以避免数据不一致或竞态条件。

回到顶部