将参数通过引用传递给 fmt。

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

Pass arguments by reference to fmt

问题

如何在Go中打印而不通过值传递(复制)给fmt?

也许可以像这样(假设使用*标志):

fmt.Printf("指针的值为 %*s", &mystruct.somelargestring)

当前的代码:

fmt.Printf("val is %v, %v\n", &mystruct.val, mystruct.Val)
val is 0xf84061d170, somestring
英文:

How do I print in go without passing arguments by value (copies) to fmt?

Perhaps something like this (hypothetical * flag)?

fmt.Printf( "Value of pointer %*s", &mystruct.somelargestring )

Currently:

fmt.Printf( "val is %v, %v\n", &mystruct.val, mystruct.Val )
val is 0xf84061d170, somestring

答案1

得分: 1

我理解你提问的原因是你担心在打印一个大字符串时会出现内存和性能问题,因为你认为会创建一个副本并传递给 fmt.Printf 函数。

在这种情况下,你不需要担心,因为传递给函数的并不是保存字符串数据的字节数组的副本。

在 Go 中,字符串是一个只读的字节切片,所以传递给函数的只是一个只读的字节切片。

在 Go 中,切片是一个值,它持有对数组元素的引用(切片[0] 处的元素),还包括切片的长度和容量等其他信息(有关切片的更详细解释,请参考下面的链接)。

重要的是要理解,切片并不持有数据(字符串的实际字节),它只持有对数据的引用。

对于字符串,切片是只读的,并且你无法直接访问底层的数组。

因此,由于你的字符串变量持有一个切片而不是底层的数组,并且切片只是对该数组的引用,当你调用 fmt.Printf 函数时,你传递的是一个引用。

在 Go 中,所有的东西都是按值传递的,但是由于你传递的是一个包含对数组引用的值,不会创建底层数组的副本;只会创建一个包含对底层数组引用的值的副本,这是很廉价的,所以你可以这样使用:

fmt.Printf("%s", mystruct.somelargestring)

而不会创建任何大字符串的副本。

为了澄清上述内容,阅读以下文章可能会有所帮助:

http://blog.golang.org/go-slices-usage-and-internals

http://blog.golang.org/slices

Go 语言规范也会有所帮助。

英文:

I understand that your reason for asking is that you are concerned about memory and performance issues when printing a large string, since you believe that a copy will be made and passed into the fmt.Printf function.

You do not have to worry about that in this case, because a copy of the byte array holding your string data is not what gets passed into the function.

In Go, a string is a read-only byte slice, so what gets passed into the function is just that - a read-only byte slice.

A slice in go is a value that holds a reference to an element of an array (the element at slice[0]), amongst other things, like the length of the slice and its capacity (see links below for a more in-depth explanation of slices).

It is important to understand that a slice does not hold the data (actual bytes of your string) - it only holds a reference to that data.

In the case of a string, the slice is read-only and you don't have direct access to the underlying array.

So, since your string variable holds a slice and not the underlying array and a slice is only a reference to that array, when you call the fmt.Printf function, you are passing a reference.

Everything in Go gets passed by value, sure, but since what you are passing is a value that contains a reference to you array, a copy of the underlying array won't get made; only a copy of the value holding the reference to the underlying array gets made, which is cheap, so you can use:

fmt.Printf( "%s", mystruct.somelargestring )

without any copies of your large string being made.

To clarify the above, it would be helpful for you to read:

http://blog.golang.org/go-slices-usage-and-internals

and

http://blog.golang.org/slices

The Go Language Specification would also help a bit.

答案2

得分: 0

如果你正在使用指针,fmt.Printf会使用指针的副本(即"指针值"的副本),而不是对象本身的副本。参见调用

> 在函数调用中,函数值和参数按照通常的顺序进行评估。在它们被评估之后,调用的参数以按值传递的方式传递给函数,并且被调用的函数开始执行。

我通常这样使用:

myobject *MyObject
fmt.Printf("%v", myObject)
英文:

If you are using a pointer, fmt.Printf will use a copy of the pointer (a copy of the "pointer value"), not a copy of the object itself.
See Calls:

> In a function call, the function value and arguments are evaluated in the usual order.
After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution.

I usually use:

myobject *MyObject
fmt.Printf("%v", myObject)

huangapple
  • 本文由 发表于 2014年9月9日 22:29:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/25747225.html
匿名

发表评论

匿名网友

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

确定