Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does fmt.Printf accept a byte array for %x in Go

Tags:

go

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!

like image 836
Hot.PxL Avatar asked May 02 '14 07:05

Hot.PxL


1 Answers

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 takes interface{} values
  • It introspects the interface{} values to print lots of different things

I hope that explanation is helpful!

like image 92
Nick Craig-Wood Avatar answered Oct 15 '22 13:10

Nick Craig-Wood