【问题标题】:Pass a slice by reference to a function and modify the original slice [duplicate]通过引用函数传递切片并修改原始切片[重复]
【发布时间】:2021-10-26 09:22:50
【问题描述】:

我目前正在学习 Go 编程语言。

我创建了一个 pop() 函数来从切片中弹出元素。

目前我是这样实现的:

func pop(s []int) (int, []int) {
    val := s[len(s)-1]
    return val, s[:len(s)-1]
}

func main() {
    elem, newSlice := pop([]int{1, 2, 3, 4, 5})
    fmt.Printf("Popped: %v\nNew SLice: %v\n", elem, newSlice)
}

这按预期工作,但我想知道是否有一种方法可以引用原始切片并删除元素而无需返回副本。我不确定我是否理解如何将切片的指针传递给函数(我认为它们已经是对底层数组的引用)。是否可以传递对切片的引用并在函数范围内修改原始切片?

【问题讨论】:

  • 我试图以这种方式传递它并不断收到无效参数错误。奇怪。
  • @mh-cbon 谢谢你的例子!我试图将它封装到一个 pop() 函数中。

标签: arrays go pointers slice


【解决方案1】:

根据mh-cbon的建议,可以对原切片进行如下修改:

package main

import (
    "fmt"
)

func main() {
    s := []int{1, 2, 3, 4, 5}
    elem := s[len(s)-1 : len(s)]

    popped := s[:len(s)-1]
    fmt.Printf("Popped: %v\nNew SLice: %v\n", elem, popped)
}

输出:

Popped: [5]
New SLice: [1 2 3 4]

【讨论】:

  • 我建议,因为它是执行该操作的最快方法,而且在我看来,这就是语言的精神。如果我错了,请纠正我。
【解决方案2】:

Go 中没有引用类型(在 C 中的经典意义上)。切片是一个类似结构的标头,包含指向后备数组的指针。 Go 中的所有内容都是按值传递的。这就是为什么内置 append() 还返回新切片,如果您需要新切片,您应该分配该切片。返回一个新切片是完全可以的。

如果确实需要修改原始切片(不返回和赋值),则必须使用指向它的指针,例如:

func pop(s *[]int) int {
    val := (*s)[len(*s)-1]
    *s = (*s)[:len(*s)-1]
    return val
}

func main() {
    s := []int{1, 2, 3, 4, 5}
    elem := pop(&s)
    fmt.Printf("Popped: %v\nNew SLice: %v\n", elem, s)
}

这将输出(在Go Playground 上尝试):

Popped: 5
New SLice: [1 2 3 4]

查看相关问题:

Are slices passed by value?

Confused about append() behavior on slices

slice vs map to be used in parameter

Slicing a slice pointer passed as argument

【讨论】:

  • 哦!好的!我看到我在尝试传递指针时做错了什么。我没有将 s 的地址传递给 pop!谢谢!!这有帮助!
猜你喜欢
  • 2018-08-31
  • 2017-02-10
  • 2021-10-28
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 2013-09-14
相关资源
最近更新 更多