英文:
Passing slice to Scanf
问题
代码段中的内容是关于使用fmt.Scanf
函数读取输入并保存到切片中的问题。你想知道为什么需要将数组元素的指针传递给函数,并且如果不使用指针作为参数,后续的值将无法读取。
首先,对于fmt.Scanf
函数,它需要传递参数的指针,以便能够将输入的值保存到指定的内存地址中。对于切片或数组来说,它们是通过指针来引用底层数据的,因此需要传递指针才能正确地读取和保存值。
在第一个示例中,当你使用mapIsh[0]
等作为参数传递给fmt.Scanf
时,实际上是将切片的值传递给函数,而不是指向切片元素的指针。因此,fmt.Scanf
无法将输入的值保存到切片中,导致输出为0。
在第二个示例中,你正确地将切片元素的指针传递给了fmt.Scanf
,因此它能够将输入的值保存到切片中,并正确地输出了1和2。但是,对于其他的元素,你没有传递指针,导致它们的值仍然为0。
因此,为了正确地读取和保存输入的值到切片中,你需要将所有的切片元素都传递给fmt.Scanf
的指针参数。这样,函数才能够将输入的值保存到切片中,并正确地输出它们。
英文:
The snippet:
package main
import "fmt"
func main() {
mapIsh := make([]int64, 5)
fmt.Scanf("%v %v %v %v %v", &mapIsh[0], &mapIsh[1], &mapIsh[2], &mapIsh[3], &mapIsh[4])
fmt.Print(mapIsh[0], mapIsh[1], mapIsh[2], mapIsh[3], mapIsh[4])
}
I crate a slice and want to save the contents of a read operation. The above works as expected. What i don't get is why I have to pass pointers to the array elements(I assumed the values are passed by reference for slices/arrays).
Also if I don't make one of the arguments a pointer the subsequent values wont be read. So can someone explain the following:
Input data: 1 2 3 4 5
-
For:
fmt.Scanf("%v %v %v %v %v", mapIsh[0], mapIsh[1], mapIsh[2], mapIsh[3], mapIsh[4])
I get: 0 0 0 0 0
-
For:
fmt.Scanf("%v %v %v %v %v", &mapIsh[0], &mapIsh[1], mapIsh[2], &mapIsh[3], &mapIsh[4])
I get: 1 2 0 0 0
答案1
得分: 2
在Go语言中,参数始终按值传递,而不是按引用传递。
你说得对,将切片传递给函数可以使函数修改其元素。但是你并没有将切片传递给Scanf
函数;你的两个示例是将int64元素传递给函数,而不是传递这些元素的地址。我认为你被索引语法所迷惑,认为mapIsh[0]
表示你传递给函数的是可以修改的内容。但是,mapIsh[0]
实际上只是一个int64类型的值,是mapIsh
的第一个元素。
至于为什么你得到的是零值,那是因为Go将mapIsh
初始化为零值,对于int64数组来说,零值就是全0。当Scanf
无法读取你忘记加&
的值时,它无法继续执行。这就是为什么你应该检查Scanf
返回的错误,它会指示错误的原因。
(请注意,按值传递意味着将数组传递给函数会创建该数组的副本,因此函数无法像对待切片那样修改元素。但在这里并不相关,如上所述。)
英文:
Arguments are always passed by value in Go, never by reference.
You're right that passing a slice to a function would allow the function to mutate its elements. But you're not passing a slice into Scanf
; your two examples are passing in the int64 elements versus passing in the addresses of those elements. I think you're getting confused by the indexing syntax and thinking mapIsh[0]
somehow means you're passing in something the function will be able to mutate. But mapIsh[0]
really is just an int64, the first element of mapIsh
.
As for why you're getting zeros, that's because Go initializes mapIsh
to the zero-value, which for an array of int64s is all 0s. When Scanf
can't read into the value you forgot the &
for, it was not able to continue. This is why you should check the error returned from Scanf
, which will indicate the error.
(Note that pass-by-value means that passing an array to a function creates a copy of that array, so the function will not be able to mutate the elements like it can for a slice. That isn't actually relevant here, as described above.)
答案2
得分: 1
首先,对于切片/数组,值不会通过引用传递。
同时,如果你将一个切片值传递给某个函数,接收者将能够修改相同的底层数组,因为切片值包含一个指针。
在你的情况下,你并没有传递切片本身,而是传递了解引用的int64
值的副本。而且fmt.Scanf
并没有更新mapIsh
。只有通过传递地址,你才能使用扫描到的值。
英文:
First of all, values are not passed by reference for slices/arrays.
At the same time, if you were passing a slice value to some function, the receiver would be able to modify the same underlying array, because a slice value contains a pointer.
In your case, you are not passing a slice itself, but rather copies of the dereferenced int64
values. And fmt.Scanf
is not updating mapIsh
. Only passing addresses are you able to use the scanned values.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论