当前位置: 首页 > 面试题库 >

Go中的“值语义”和“指针语义”是什么意思?

华良才
2023-03-14
问题内容

Go中的 Value语义Pointer语义
是什么意思?在本课程中,作者在解释数组和切片的内部时曾经多次提到上述术语,而我对此并不完全理解。


问题答案:

当您调用一个函数或方法并将参数传递给它时,将根据值创建一个副本,并且该函数只能访问这些副本。

这意味着,如果函数尝试修改/更改副本,则不会更改原始值。

例如:

func main() {
    i := 1
    fmt.Println("double:", double(i))
    fmt.Println("original i:", i)
}

func double(i int) int {
    i *= 2
    return i
}

输出(在Go Playground上尝试):

double: 2
original i: 1

即使double()修改了其i参数,调用方的变量(已传递其值)也没有改变。

要更改它,我们需要更改签名以期望有一个指针,传递一个指针并修改指向的值:

func main() {
    i := 1
    fmt.Println("double:", doublep(&i))
    fmt.Println("original i:", i)
}

func doublep(i *int) int {
    *i *= 2
    return *i
}

输出(在Go Playground上尝试):

double: 2
original i: 2

因此,如果我们传递一些东西,我们期望如果传递的值被修改,原始值将不会改变,除非我们传递指向它的指针。

指针语义 意味着,即使我们通过“按值”传递某些内容,被调用方仍然可以修改“原始”值,就像我们已经将指针传递给它一样。

例如:

func main() {
    is := []int{1, 2}
    fmt.Println("double:", doubles(is))
    fmt.Println("original is:", is)
}

func doubles(is []int) []int {
    for i := range is {
        is[i] *= 2
    }
    return is
}

输出(在Go Playground上尝试):

double: [2 4]
original is: [2 4]

即使我们没有传递指针(is不是指针),被调用者仍会修改其元素,并且原始切片的值也会更改。

我们说,即使在Go语言中,所有内容都按值传递,但传递的切片具有指针语义,因为如果被调用者修改了元素,它将反映在原始元素中。

推理

Go中的所有内容都按值传递,也是如此。但是,切片是在幕后,是类似结构的数据结构,该数据结构包含指向保存实际元素的基础数组的指针。并且,当您传递切片时,将进行复制,但是只会复制此切片标头(这是切片值)。副本将包含相同的指针,指向相同的后备数组。没有复制后备阵列。因此,当被调用方修改切片的元素时,支持数组的元素也将被修改,这与原始切片的支持数组相同。

在此处了解更多信息:golang切片是否按值传递?

指针语义传递了许多类型,例如切片,地图,通道。

值得注意的是,与切片不同,数组不在行中,数组值表示其所有值,而传递数组则表示其所有元素的副本。



 类似资料:
  • 问题内容: “值语义”是什么意思,“隐式指针语义”是什么意思? 问题答案: Java对对象类型使用隐式指针语义,对基元使用值语义。 值语义意味着您直接处理值,并传递副本。这里的重点是,当您拥有一个价值时,您可以相信它不会在您的背后改变。 使用指针语义时,您没有值,而您有一个“地址”。别人可能会改变那里的东西,你不知道。 C ++中的指针语义: 您需要*来询问指针语义,并需要->来调用pointee

  • 问题内容: 我只是在玩Go,还没有关于何时按值或按引用传递结构的良好心理模型。 这可能是一个非常愚蠢的问题,但我只想尝试一下,看看我是否仍在处理同一对象,或者是否已对其进行了复制(按值传递)。 有没有一种方法可以打印对象的指针(如果gc更改了指针值,则为内部ID)? 在我的Windows上给出(8g编译版本): 为什么go例程中的指针值显示不同的值?原始对象上的数量确实发生了更改,因此它正在使用同

  • 问题内容: 我已经在CSS对话中看到了很多。语义正确是什么意思? 问题答案: 正确贴标签 这意味着您正在调用的东西实际上是什么。经典示例是,如果某物为,则应包含数据的行和列。将其用于布局在语义上是不正确的- 如果不是,则是说“这是一个表”。 另一个示例:通常应使用列表(或)对相似项()进行分组。您 可以 将a 用于组,将a 用于每个项目,然后将每个项目的样式设置为在单独的行上并带有一个项目符号点,

  • 问题内容: 通过与这个有关标签的问题进行类比,我注意到,除了纯注释之外,注释还有多种用途。 例子: go:generate可用于代码生成。 godoc使用函数名称表示应解释的注释 建立约束 还有其他我想念的吗? 那里有确定的清单吗? gocontracts和go- swagger 等一些第三方软件包也可以使用它们。他们如何避免彼此冲突? 问题答案: 如前所述,注释不仅是注释,而且是指令。 撰写本文

  • 问题内容: 我正在寻找有关Google Go语言的信息。在“ A Go of Go”中,他们具有以下代码: 但是什么和 意味着什么呢? 您可以在http://tour.golang.org/#14上查看所有代码 问题答案: 它们是按位移位运算符。表示 x ×2 y ,而表示 x ×2 -y 或等效地x÷2 y。这些运算符通常用于操作值的二进制表示形式,就像十进制的10的幂一样,乘或除以2的幂分别具

  • 主要内容:认识指针地址和指针类型,从指针获取指针指向的值,使用指针修改值,示例:使用指针变量获取命令行的输入信息,创建指针的另一种方法——new() 函数与 Java 和 .NET 等编程语言不同,Go语言为程序员提供了控制 数据结构指针的能力,但是,并不能进行指针运算。Go语言允许你控制特定集合的数据结构、分配的数量以及内存访问模式,这对于构建运行良好的系统是非常重要的。指针对于性能的影响不言而喻,如果你想要做系统编程、操作系统或者网络应用,指针更是不可或缺的一部分。 指针(pointer)在