英文:
Why does fmt.Printf accept a byte array for %x in Go
问题
我对Go语言还不太熟悉。我想知道数组和切片之间的确切区别,请原谅我对规范过于执着。
在fmt
包的文档中,对于Printf
函数,它说%x
可以接受字符串和字节切片。但它没有提到字节数组。但实际上,如果我将一个字节数组放进去,它也可以正常打印出来!
package main
import (
"fmt"
)
func main() {
var b [6]byte
for i := 0; i < 6; i++ {
b[i] = 'a'
}
fmt.Printf("%s\n", b) // "aaaaaa"
}
有人能告诉我为什么吗?据我所知,字节数组和切片不能隐式地相互转换。
谢谢阅读我的问题!
英文:
I'm pretty new to Go. I want to know the exact difference between arrays and slices so please forgive me if I'm too obsessive over the spec.
In documentation for package fmt
, it says for Printf
that %x
can accept strings and slices of bytes. It said nothing about arrays of bytes. But in fact, if I put an array of bytes in it, it prints out fine too!
package main
import (
"fmt"
)
func main() {
var b [6]byte
for i := 0; i < 6; i++ {
b[i] = 'a'
}
fmt.Printf("%s\n", b) // "aaaaaa"
}
Can anyone please tell me why? AFAIK, bytes array and slices cannot implicitly convert to each other.
Thanks for reading my question!
答案1
得分: 12
你是正确的,你不能隐式地转换切片和数组。
切片是一个小的数据结构,包含三个元素:指向某个内存的指针、内存的长度和内存的容量。
然而,数组只是一块内存。
Go 在函数中将所有内容都按值传递,这意味着当你用数组调用 Printf
时,整个数组的内存都会传递给函数。当你用切片调用它时,整个切片结构都会传递给 Printf
。然而,切片结构包含指向底层内存的指针,所以这很像是传递一个指向数组的指针。
Printf
使用了很多内省来打印其值。Printf
的所有参数都被转换为 interface{}
类型,这意味着它们被封装在一个带有类型的小结构中。然后,Printf
检查这些接口值,检查类型并确定如何打印这些值。对于大多数 %
类型,Printf
可以接受多种类型,并尝试以用户友好的方式打印它们。
例如,%x
可以接受一个以十六进制打印的 int
,或者一个切片,或者一个数组,正如你已经发现的那样。
所以总结一下:
- 数组是连续的内存
- 切片是一个包含指向连续内存的指针的结构
- 接口值是一个小结构,包含指向类型和值的指针
Printf
接受interface{}
值- 它内省
interface{}
值以打印很多不同的东西
希望这个解释对你有帮助!
英文:
You are correct that you can't implicitly convert slices and arrays.
A slice is a small data structure with 3 elements which are a pointer to some memory, the length of the memory, and the capacity of the memory.
However an array is just a block of memory.
Go passes everything by value in functions meaning that when you call Printf
with the array, the whole of the memory of the array is passed to the function. When you call it with a slice, the whole of the slice structure is passed to Printf
. However the slice structure contains a pointer to the underlying memory so this is very like passing a pointer to an array.
Printf
uses lots of introspection to print its values. All the arguments to Printf
are converted to interface{}
types which means they are boxed up with a type in a small structure. Printf
then examines these interface values, inspects the type and works out how to print the values. For most %
types that Printf
undestands it can take quite a few types and it attempts to print them in a user friendly way.
For example %x
can take an int
which is printed in hex, or a slice, or an array as you've discovered.
So in summary
- array is contiguous memory
- slice is a structure containing a pointer to contiguous memory
- an interface value is a small structure containing a pointer to a type and the value
Printf
takesinterface{}
values- It introspects the
interface{}
values to print lots of different things
I hope that explanation is helpful!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论