gpt4 book ai didi

arrays - 我可以使用单行从 slice 中的位置 n 弹出一个元素吗?

转载 作者:行者123 更新时间:2023-12-01 20:25:48 25 4
gpt4 key购买 nike

我正在通过 slice tricks文档并看到一些单线弹出和弹出前面。例如,这两个工作正常:

// pop
s := []int{1, 2, 3}
last, s := s[len(s)-1], s[:len(s)-1]
fmt.Println(last, s) // Prints 3 [1 2]
// pop front
s := []int{1, 2, 3}
first, s := s[0], s[1:]
fmt.Println(first, s) // Prints 1 [2 3]
但是如果我尝试做这样的事情来弹出第二个元素:
s := []int{1, 2, 3}     
second, s := s[1], append(s[0:1], s[2:]...)
fmt.Println(second, s) // Prints 3 [1 3]
它弹出第二个元素,但 second变量指向新 slice 的第二个元素。为什么这种情况发生在这种情况下而不是前两种情况?为了工作,我必须使用单独的行:
s := []int{1, 2, 3}                     
second := s[1]
s = append(s[0:1], s[2:]...)
fmt.Println(second, s) // Prints 2 [1 3]

最佳答案

Go spec section on assignments告诉我们这是

second form


元组赋值。它接着说:

The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.


所以编译器计算出 seconds将通过为赋值目的对它们求值来赋值——这或多或少只产生它们的名称1——并且还对右侧的表达式求值

the usual order


这意味着我们必须按照链接查看“通常的顺序”是什么意思。这让我们到 Order of evaluation .
这里的文字有点棘手,但这个例子很有启发性:

in the (function-local) assignment

y[f()], ok = g(h(), i()+x[j()], <-c), k()

the function calls and communication happen in the order f(), h(), i(), j(), <-c, g(), and k(). However, the order of those events compared to the evaluation and indexing of x and the evaluation of y is not specified.


让我们将其与您自己的表达进行比较:
second, s := s[1], append(s[0:1], s[2:]...)

我们知道 append将在之前被调用......好吧,我们并不确定:没有进一步的(调用权)函数调用或 channel 调用。但显然它必须在 s 之前调用可以赋值。
但是,与此同时,此调用相对于“评估和索引” s[1] 的顺序。没有明确规定。如果先完成, append操作将(可能 2)就地修改支持 slice 的数组 s[0:1] .
那么,显然正在发生的是 append(s[0:1], s[2:]...)实际上是在原地修改数组。然后是评价和索引 s[1]发生,并修改了数组。这将获取 s[1] 的修改值并将其复制到变量 second .

Why does that happen for this case but not for the first two?


那些不叫 append因此不允许 append就地修改数组。

1由于在内部使用 SSA,这些变成了对新变量的赋值,就像它一样,但最终结果都是一样的。
2由 append决定函数来决定是进行就地修改,还是创建一个新的支持数组。但是,在这种情况下,由于我们正在缩小总长度,这显然是可能的,并且实际实现每次都会利用这一点 - 尽管也没有指定!

结论
这里要做的事情是编写一个执行提取和更新的小函数,而不是单行函数,并简单地允许编译器将其内联为相当快的内容。当然,这让我们希望使用泛型,因此需要 Go 2。

关于arrays - 我可以使用单行从 slice 中的位置 n 弹出一个元素吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63760036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com