在Golang,我正在尝试为我的旅行推销员问题制作一个争夺切片功能.虽然这样做我注意到当我开始编辑切片时,我给每个传递它时的加扰功能是不同的.
经过一些调试后我发现它是由于我编辑了函数内部的切片.但由于Golang应该是一种"通过价值传递"的语言,这怎么可能呢?
https://play.golang.org/p/mMivoH0TuV
我提供了一个游乐场链接来展示我的意思.通过删除第27行,您获得的输出与输入不同,这应该没有区别,因为该函数在作为参数传入时应该创建自己的切片副本.
有人可以解释这种现象吗?
最近读了《Go编程语言书》,这是学习golang编程语言的好资源。\n6.2节中有一段关于类型的复制实例T
在方法中是否是指针接收者时类型的复制实例,我无法理解。 \n有没有用一个有意义的例子来解释这一段?
\n\n6.2 使用指针接收器的方法
\n\n如果命名类型 T 的所有方法都有 T 本身的接收者类型(不是 *T ),则复制该类型的实例是安全的;调用它的任何方法都必然会生成一个副本。例如,time.Duration 值可以自由复制,包括作为函数的参数。但是,如果任何方法具有指针接收器,则应避免复制 T 的实例,因为这样做可能会违反内部不变量。例如,复制 bytes.Buffer 的实例将导致原始和副本为相同的底层字节数组别名( \xc2\xa72.3.2 )。后续的方法调用将产生不可预测的效果。
\n\n(Go 编程语言 Alan AA Donovan \xc2\xb7 Brian W. Kernighan)
\n
Go中的值语义和指针语义是什么意思?在本课程中,作者在解释数组和切片的内部时,曾经多次提及上述术语,我完全无法理解.
在golang中,切片和贴图都是引用类型.当您只需要修改切片/贴图中的元素时,切片/贴图成员的修改将"广播"到所有切片.例如,给定m1 := make(map[int]int); m2 := m1
,m1[3] = 5
将导致m2[3] == 5
.
但是,当您尝试将新元素添加到这两种类型时,事情开始有所不同.如下例所示,添加到地图参数中的新元素将自动显示在参数中; 但是,添加到切片中的新元素在参数中被"丢弃".
问题是,为什么这有区别?
func editMap(m map[int]int) {
m[3] = 8
m[4] = 9
}
func editSlice(s []int) {
s = append(s, 5)
s = append(s, 9)
}
func main() {
m := make(map[int]int, 0)
m[1] = 5
m[2] = 3
fmt.Printf("%v\n", m) //map[1:5 2:3]
editMap(m)
fmt.Printf("%v\n", m) //map[1:5 2:3 3:8 4:9]
s := make([]int, 2)
s[0] = 2
s[1] = 5
fmt.Printf("%v\n", s) //[2 …
Run Code Online (Sandbox Code Playgroud) 有人可以帮助我理解这里发生了什么吗?
package main
import (
"fmt"
)
func appendString(slice []string, newString string) {
slice = append(slice, newString)
}
func main() {
slice := make([]string, 0, 1)
appendString(slice, "a")
fmt.Println(slice)
}
Run Code Online (Sandbox Code Playgroud)
我了解切片头以及使用指针接收器的需要。但在这里,由于底层数组有足够的容量,我希望追加能够正常工作(只需将新值添加到底层数组中,原始的[复制]标头按预期工作)
我的假设有什么问题吗?
我正在使用 Golang 将大量 CSV 文件加载到结构中。结构是
type csvData struct {
Index []time.Time
Columns map[string][]float64
}
Run Code Online (Sandbox Code Playgroud)
我有一个解析器使用:
csv.NewReader(file).ReadAll()
Run Code Online (Sandbox Code Playgroud)
然后我迭代行,并将值转换为其类型:time.Time
或float64
。
问题是这些文件在磁盘上占用了 5GB 空间。一旦我将它们加载到内存中,它们就会消耗 12GB!
我使用ioutil.ReadFile(path)
后发现,正如预期的那样,这几乎与磁盘上的大小完全相同。
这是我的解析器的代码,为了可读性省略了错误,如果您可以帮助我排除故障:
csv.NewReader(file).ReadAll()
Run Code Online (Sandbox Code Playgroud)
我尝试通过在函数调用结束时将columnData
和设置为 nil 来进行故障排除,但没有任何变化。reader
我正在解决这个 Project Euler 问题。首先我尝试了暴力破解,花了 0.5 秒,然后我尝试了动态编程来利用记忆化,期望有巨大的改进,但令我惊讶的是结果是 0.36 秒。
经过一番谷歌搜索后,我发现您不能在函数(find_collatz_len)中使用指向外部地图数据(备忘录)的指针。因此,每次运行下面的函数时,它都会复制整个字典。这听起来像是对处理器能力的巨大浪费。
我的问题是有什么解决方法,以便我可以使用指向函数外部映射的指针来避免复制。
这是我的丑陋代码:
package main
//project euler 014 - longest collatz sequence
import (
"fmt"
"time"
)
func find_collatz_len(n int, memo map[int]int) int {
counter := 1
initital_value := n
for n != 1 {
counter++
if n < initital_value {
counter = counter + memo[n]
break
}
if n%2 == 0 {
n = int(float64(n)/2)
} else {
n = n*3+1
}
}
memo[initital_value] = counter
return counter
} …
Run Code Online (Sandbox Code Playgroud)