Arrays 我是否可以使用一个内衬从切片中的位置n弹出一个元素?
我正在看文件,看到一些一行一行的东西在前面蹦蹦跳跳。例如,这两种方法可以很好地工作:Arrays 我是否可以使用一个内衬从切片中的位置n弹出一个元素?,arrays,go,slice,Arrays,Go,Slice,我正在看文件,看到一些一行一行的东西在前面蹦蹦跳跳。例如,这两种方法可以很好地工作: //pop s:=[]int{1,2,3} 最后,s:=s[len(s)-1],s[:len(s)-1] fmt.Println(last,s)//打印3[12] //弹出式前端 s:=[]int{1,2,3} 首先,s:=s[0],s[1:] fmt.Println(第一,s)//打印1[2 3] 但是如果我尝试这样做来弹出第二个元素: s:=[]int{1,2,3} 第二,s:=s[1],追加(s[0:
//pop
s:=[]int{1,2,3}
最后,s:=s[len(s)-1],s[:len(s)-1]
fmt.Println(last,s)//打印3[12]
//弹出式前端
s:=[]int{1,2,3}
首先,s:=s[0],s[1:]
fmt.Println(第一,s)//打印1[2 3]
但是如果我尝试这样做来弹出第二个元素:
s:=[]int{1,2,3}
第二,s:=s[1],追加(s[0:1],s[2:]…)
fmt.Println(第二,s)//打印3[13]
它弹出第二个元素,但second
变量指向新切片中的第二个元素。为什么这种情况会发生,而不是前两种情况?为了工作,我必须使用单独的行:
s:=[]int{1,2,3}
第二:=s[1]
s=追加(s[0:1],s[2:]…)
fmt.Println(第二,s)//打印2[13]
告诉我们这是
第二种形式
元组赋值的性质。它接着说:
转让分两个阶段进行。首先,左侧和(包括中的隐式指针间接)的操作数和右侧的表达式都是。其次,作业按从左到右的顺序进行
因此,编译器通过计算second
和s
的赋值目的,计算出要赋值的second
和s
,这些赋值目的只是生成它们的名称,或多或少1,还计算
通常的顺序
这意味着我们必须通过链接来了解“常规顺序”的含义。这让我们有机会
这里的文字有点棘手,但示例很有启发性:
在(函数本地)赋值中
y[f()], ok = g(h(), i()+x[j()], <-c), k()
我们知道,append
将在。。。好吧,我们并不确定:并没有进一步的(调用右侧)函数调用或通道调用。但显然,必须先调用它,然后才能将s
分配到
但是,同时,没有明确指定此调用相对于“s[1]
的“求值和索引”的顺序。如果先完成,则追加
操作将(可能2)在位修改支持切片的数组s[0:1]
很明显,append(s[0:1],s[2:]…)
实际上是在修改数组。然后执行求值和索引s[1]
,修改数组。这将获取s[1]
的修改值,并将其复制到变量second
为什么这种情况会发生,而不是前两种情况
它们不调用append
,因此不允许append
就地修改数组
1由于SSA在内部的使用,这些变量实际上变成了新变量的赋值,但最终结果都是一样的 2由
append
函数决定是就地修改还是创建新的备份阵列。不过,在这种情况下,由于我们正在缩小总长度,这显然是可能的,而实际的实现每次都会利用这一点,尽管也没有指定
结论 这里要做的是编写一个执行提取和更新的小函数,而不是作为一个线性函数,并允许编译器以相当快的速度将其内联。当然,这让我们希望使用泛型,因此使用Go 2
second, s := s[1], append(s[0:1], s[2:]...)