Golang Go语言中的一个切片问题请教

发布于 1周前 作者 wuwangju 来自 Go语言
package main

import “fmt”

type pq struct { arr []int }

func (q *pq) put(num int) { // 从小到大的顺序插入进去 index := b_s(q.arr, num) if index >= len(q.arr) { // 直接插到最后一个数位 q.arr = append(q.arr, num) } else { tmp := append(q.arr[:index], num) tmp = append(tmp, q.arr[index:]…) q.arr = tmp }

}

func (q *pq) get() int { if len(q.arr) > 0 { num := q.arr[0] q.arr = q.arr[1:] return num } panic(“arr is empty!!!”) }

func (q *pq) getSize() int { return len(q.arr) }

func b_s(arr []int, target_num int) int { if len(arr) == 0 { return 0 } else { left, right := 0, len(arr)-1 for { if right-left <= 1 { if target_num <= arr[left] { return left } else if target_num <= arr[right] { return right } else { return right + 1 } } else { mid := (left + right) / 2 if arr[mid] == target_num { return mid } else if arr[mid] < target_num { left = mid } else { right = mid } } } } }

func main() { s := &pq{arr: make([]int, 0)} s.put(20) s.put(3) s.put(30) fmt.Println(s.arr) }

请教一下输出的为什么不是[3 20 30] 呀, 感觉使用好像和 python 的不太一样


Golang Go语言中的一个切片问题请教

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

6 回复

很明显不是切片的问题, 算法没写对呗

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


tmp := append(q.arr[:index], num) 这句会覆写后面已有的数据

大佬, 由于我这边是从 python 转过来的,python 类似的就是这样的写法,不知道这样具体有啥问题呢。

tmp := append(q.arr[:index], num);可以看做两条语句:
a := q.arr[:index];
tmp := append(a,num);
问题的关键在于关键的问题:a 虽然是一个新的切片变量,但是 a 的底层数据结构——数组是和 q.arr 共享的;因此 tmp := append(a,num); 相当于把 num 放到了底层数组 index 的位置,那么从 q.arr 的角度来看,就是数据被覆盖了;
可以尝试新创建一个数组,然后 copy 一下;

感谢大佬,看了一下解释,
第一次 put(20)的时候是正常没有问题,
第二次 put(3)的时候是发生了以下的过程
首先计算出来 index=0 ,
所以
tmp := append(q.arr[:index], num)就变成了以下两个步骤
a := q.arr[:0], 所以切片截取之后 a 和 q.arr 的 header 地址相同,len 不同,q.arr 是 1 ,a=0 ,cap 一样,
tmp := append(a, num), 此时没有发生扩容,所以 a 和 q.arr 还是使用的同一片地址, 所以第一个元素就改成了 num 就是 3 了

tmp = append(tmp, q.arr[index:]…)
所以此时 q.arr[index:] 就是 等于 [3]了
此时 append 进行了扩容,tmp 会迁移到一个新的地址当中,所以此时 tmp 就是[3, 3]了, 而之前的 q.arr 还是[3]

之后 put(30)就是正常的操作了。

当然可以,以下是对帖子内容的回复:


关于Golang(Go语言)中的切片问题,这是一个非常常见且重要的主题。切片是Go语言中的一种动态数组,提供了灵活且高效的数组操作方式。

首先,需要明确的是,切片是对底层数组的抽象,它包含指向数组起始元素的指针、长度以及容量。因此,当你对一个切片进行操作时,实际上是在操作其背后的数组。

如果你遇到了切片的具体问题,比如切片扩容、切片复制、切片遍历等,这里有一些可能的解决方案:

  1. 切片扩容:当向切片添加元素时,如果容量不足,Go会自动进行扩容。扩容策略通常是按照倍数增长,但这是一个实现细节,可能因版本而异。

  2. 切片复制:可以使用内置的copy函数来复制切片。注意,copy只会复制元素,不会复制底层数组。

  3. 切片遍历:可以使用for循环来遍历切片,同时获取索引和值。

此外,还有一些常见的切片陷阱需要注意,比如切片越界、切片共享底层数组导致的意外修改等。为了避免这些问题,建议在使用切片时始终保持清晰的思维,并注意切片操作的边界条件。

如果你能提供更具体的切片问题(比如代码示例和错误描述),我可以给出更精确的帮助。希望这些信息对你有所帮助!


回到顶部