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

Golang函数参数是否以写时复制形式传递?

吕晟睿
2023-03-14
问题内容

我有以下功能:

func checkFiles(path string, excludedPatterns []string) {
    // ...
}

我想知道,由于excludedPatterns从未更改过,我应该通过使var全局(而不是每次都将其传递给函数)来优化它,还是Golang已经通过将它们作为写时复制传递来处理了?

编辑:我想我可以将切片作为指针传递,但是我仍然想知道写时复制行为(如果存在)以及通常是否应该担心按值或按指针传递。


问题答案:

从函数名称来看,即使考虑将参数移至全局变量以节省将参数作为参数传递所需的时间/空间,性能也不是那么关键(IO操作(如检查文件)比调用函数慢得多,而将价值传递给他们)。

Go中的slice只是小的描述符,类似于带有指向后备数组的指针和2
ints(长度和容量)的结构。不管支持数组有多大,传递切片始终是高效的,您甚至不应该考虑将指针传递给它们,除非您当然想修改切片标头。

Go中的参数始终按值传递,并复制要传递的值。如果传递指针,则将复制并传递指针值。传递切片时,将复制并传递切片值(它是一个小的描述符)-它将指向相同的后备数组(不会被复制)。

同样,如果您需要多次访问函数中的切片,则参数通常会带来额外的好处,因为编译器可以进行进一步的优化/缓存,而如果它是全局变量,则必须格外小心。

有关切片及其内部的更多信息:转到切片:用法和内部

如果您想获得准确的性能数字,请进行基准测试!

这里有一些基准测试代码,它显示了两种解决方案之间没有区别(将slice作为参数传递或访问global
slice)。将其保存到类似的文件中slices_test.go,然后使用go test -bench .

package main

import (
    "testing"
)

var gslice = make([]string, 1000)

func global(s string) {
    for i := 0; i < 100; i++ { // Cycle to access slice may times
        _ = s
        _ = gslice // Access global-slice
    }
}

func param(s string, ss []string) {
    for i := 0; i < 100; i++ { // Cycle to access slice may times
        _ = s
        _ = ss // Access parameter-slice
    }
}

func BenchmarkParameter(b *testing.B) {
    for i := 0; i < b.N; i++ {
        param("hi", gslice)
    }
}

func BenchmarkGlobal(b *testing.B) {
    for i := 0; i < b.N; i++ {
        global("hi")
    }
}

输出示例:

testing: warning: no tests to run
PASS
BenchmarkParameter-2    30000000                55.4 ns/op
BenchmarkGlobal-2       30000000                55.1 ns/op
ok      _/V_/workspace/IczaGo/src/play  3.569s


 类似资料:
  • 我想发送一个函数作为参数。当我在另一个函数中调用它“this”和其他类似“HttpClient”的函数时,“urlBase”是未定义的。 我在互联网上搜索并找到了关于bind()属性的信息,但如果现在定义了“this”,其他属性仍然没有定义。所以我把所有需要的属性都放在bind()函数中,但对我来说很糟糕。。。 这是我的服务功能,它确实工作得很好。 这是我想给它另一个函数作为参数的函数: 以及之前

  • 问题内容: 只是一个关于如何在Java中传递参数的快速问题… 在这种情况下,stdout和stderr(用作tidy()中的参数)的值是否会更改为新的StringBuffer(buffer.substring(i))?我的假设是,它们将作为对象变量(对象指针)始终按值传递吗? 问题答案: 您错报了这里发生的事情-对象引用按值传递(创建了引用的副本),因此调用tidy时 不会 修改stdout和st

  • 问题内容: 与在或中使用的方式类似: 问题答案: 是。 如果你不理会关键字参数,这很简单并且可以工作: 如你所见,Python将为你提供一个包含所有参数的元组。 对于关键字参数,你需要将其作为单独的实际参数接受,如的所示。

  • 函数取得的参数是你提供给函数的值,这样函数就可以利用这些值 做 一些事情。这些参数就像变量一样,只不过它们的值是在我们调用函数的时候定义的,而非在函数本身内赋值。 参数在函数定义的圆括号对内指定,用逗号分割。当我们调用函数的时候,我们以同样的方式提供值。注意我们使用过的术语——函数中的参数名称为 形参 而你提供给函数调用的值称为 实参 。 使用函数形参 例7.2 使用函数形参 #!/usr/bin

  • 问题内容: 我正在用PHP编程一个Web API客户端,该客户端将CSV数据解析为关联数组,并且在使用这些数组时,我想保护我的用户免受数据重复。 我的用户永远不会写这些数组(从理论上讲可以,但是在实践中没有意义)。 现在我的问题是…如果我的用户将这些数组作为方法的参数传递,PHP的写时复制机制将防止数据重复,或者任何未明确接受对数组的引用的方法都将收到完整副本的阵列? 问题答案: 顾名思义,写时复

  • 通常情况下,定义函数时都会选择有参数的函数形式,函数参数的作用是传递数据给函数,令其对接收的数据做具体的操作处理。 在使用函数时,经常会用到形式参数(简称“形参”)和实际参数(简称“实参”),二者都叫参数,之间的区别是: 形式参数:在定义函数时,函数名后面括号中的参数就是形式参数,例如: 实际参数:在调用函数时,函数名后面括号中的参数称为实际参数,也就是函数的调用者给函数的参数。例如: 实参和形参