将切片传递给Scanf函数

huangapple go评论82阅读模式
英文:

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

  1. 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

  1. 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.

huangapple
  • 本文由 发表于 2017年7月18日 18:49:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/45164649.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定