为什么fmt.Printf在Go中接受%x的字节数组

时间:2014-05-02 07:03:35

标签: 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"
}

任何人都可以告诉我为什么? AFAIK,字节数组和切片不能隐式转换为彼此。

感谢您阅读我的问题!

1 个答案:

答案 0 :(得分:9)

你是不对的,你不能隐式转换切片和数组。

切片是一个包含3个元素的小数据结构,它是指向某个内存的指针,内存的长度和内存的容量。

然而,数组只是一块内存。

Go在函数中按值传递所有内容,这意味着当您使用数组调用Printf时,数组的整个内存将传递给函数。当您使用切片调用它时,整个切片结构将传递给Printf。但是,切片结构包含指向底层内存的指针,因此这就像将指针传递给数组一样。

Printf使用大量内省来打印其值。 Printf的所有参数都转换为interface{}类型,这意味着它们被装在一个小结构中。然后Printf检查这些接口值,检查类型并确定如何打印值。对于%未定位的大多数Printf类型,它可能需要很多类型,并尝试以用户友好的方式打印它们。

例如,%x可以采用以十六进制打印的int,或者您发现的切片或数组。

总结

  • array 连续内存
  • slice是一个结构,包含指向连续内存的指针
  • 接口值是一个包含指向类型和值
  • 的指针的小结构
  • Printf获取interface{}个值
  • 它会内省interface{}值以打印许多不同的内容

我希望这个解释很有帮助!