for-range 中引用值的棘手案例
Tricky case with value-to-references in for-range
查看代码 - 您认为输出会是什么?它是 return "Third" 而不是 "Second" 我花了一段时间才明白为什么。
你知道原因吗?
我很了解按值传递和按引用传递的概念,但这种情况对于来自 Python 等语言的人来说有点棘手。所以我决定值得分享。
package main
import "fmt"
type Record struct {
Id int
Name string
}
var records = []Record{
Record{1, "First"},
Record{2, "Second"},
Record{3, "Third"},
}
func findRecod(id int) (foundRecord *Record) {
for _, record := range records {
if record.Id == id {
foundRecord = &record
// You think we can do a break here but imagine we need to do...
}
// ...something more here
}
return foundRecord
}
func main() {
foundRecord := findRecod(2)
if foundRecord == nil {
fmt.Println("Nothing found")
} else {
fmt.Println("Found: ", foundRecord.Name)
}
}
运行网上查了一下:https://play.golang.org/p/Y_iAl6m7Ms
我花了一些时间弄清楚发生了什么。
您正在 returning 指向一个 record
变量的指针,循环的每次迭代都会重复使用该变量。最后一次迭代将指针设置为第三个结构。
变量的重用具有巨大的优势。它不会在循环的每次迭代中分配内存。这节省了大量的垃圾收集时间。
这是 FAQ 中描述的众所周知的行为。
要修复它,return 一个指向切片元素的指针。它是安全的,因为切片元素在 Go 中是可引用的。
package main
import "fmt"
type Record struct {
Id int
Name string
}
var records = []Record{
Record{1, "First"},
Record{2, "Second"},
Record{3, "Third"},
}
func findRecod(id int) (foundRecord *Record) {
for i, record := range records {
if record.Id == id {
foundRecord = &records[i]
// You think we can do a break here but imagine we need to do...
}
// ...something more here
}
return foundRecord
}
func main() {
foundRecord := findRecod(2)
if foundRecord == nil {
fmt.Println("Nothing found")
} else {
fmt.Println("Found: ", foundRecord.Name)
}
}
查看代码 - 您认为输出会是什么?它是 return "Third" 而不是 "Second" 我花了一段时间才明白为什么。
你知道原因吗?
我很了解按值传递和按引用传递的概念,但这种情况对于来自 Python 等语言的人来说有点棘手。所以我决定值得分享。
package main
import "fmt"
type Record struct {
Id int
Name string
}
var records = []Record{
Record{1, "First"},
Record{2, "Second"},
Record{3, "Third"},
}
func findRecod(id int) (foundRecord *Record) {
for _, record := range records {
if record.Id == id {
foundRecord = &record
// You think we can do a break here but imagine we need to do...
}
// ...something more here
}
return foundRecord
}
func main() {
foundRecord := findRecod(2)
if foundRecord == nil {
fmt.Println("Nothing found")
} else {
fmt.Println("Found: ", foundRecord.Name)
}
}
运行网上查了一下:https://play.golang.org/p/Y_iAl6m7Ms
我花了一些时间弄清楚发生了什么。
您正在 returning 指向一个 record
变量的指针,循环的每次迭代都会重复使用该变量。最后一次迭代将指针设置为第三个结构。
变量的重用具有巨大的优势。它不会在循环的每次迭代中分配内存。这节省了大量的垃圾收集时间。
这是 FAQ 中描述的众所周知的行为。
要修复它,return 一个指向切片元素的指针。它是安全的,因为切片元素在 Go 中是可引用的。
package main
import "fmt"
type Record struct {
Id int
Name string
}
var records = []Record{
Record{1, "First"},
Record{2, "Second"},
Record{3, "Third"},
}
func findRecod(id int) (foundRecord *Record) {
for i, record := range records {
if record.Id == id {
foundRecord = &records[i]
// You think we can do a break here but imagine we need to do...
}
// ...something more here
}
return foundRecord
}
func main() {
foundRecord := findRecod(2)
if foundRecord == nil {
fmt.Println("Nothing found")
} else {
fmt.Println("Found: ", foundRecord.Name)
}
}