pretty print byte array

1,289 views
Skip to first unread message

dlin

unread,
Apr 7, 2013, 11:45:35 PM4/7/13
to golan...@googlegroups.com
As I know google plans to close google reader.  So, I post the question to stackoverflow too.

http://stackoverflow.com/questions/15870887/how-to-pretty-print-byte-array-and-char-array

In the following code, I'm trying to write a Txt() function to pretty print out my structure. It contains following minor questions in the full code:

  1. How to write one line to initialize Char array by string(line 47)
  2. How to speed up checking Char type without strings function(line 29,30)
  3. How to print out Char array as string(line 32)
  4. How to print out Char as string, maybe use Sprintf("%c"), but it is very slow.(line 34)

full code at: http://play.golang.org/p/nUsg_qbufP

Kevin Gillette

unread,
Apr 8, 2013, 12:21:58 AM4/8/13
to golan...@googlegroups.com
Some questions:

Why do you need to re-type byte as Char? By doing so, you're making []byte (which is a "slice", not an "array") conversion-incompatible with []Char.  I don't see any methods on Char, for example, or any other reason why you'd really need to avoid using byte directly. Also, in Go, it's much more common to type a container, such as `type Chars []byte` rather than an element, as you do with `type byte Char`, and even that isn't often done unless methods are defined on the named type.  Nonetheless, you can initialize []Char from a string by doing: []Char("the string")

You cannot initialize a byte-array (or Char-array) with a fixed length from a string. Usually that does not come up as an issue, since for constant immutable data, strings are preferably used. When you really need to initialize an array, either the way you're doing it, element by element in an array literal, or slicing it and using copy (or doing something in a loop) are the only real means of initialization.

reflect, while not necessarily slower than in other reflective languages, is much slower than not using reflection. That said, fmt uses reflection in all but the easy cases, and for output, it's reasonably fast enough.

See reflect.Kind, and the reflect.Type and reflect.Value Kind method. You can check that against the constant reflect.Array to see if something is an array, and use reflect.Type's Elem method to get the element type for an array, slice, chan, etc. You can compare the returned element type for equality with reflect.TypeOf(Char(0)) to see if the element type is a Char, without needing to do any string manipulation.

What is your actual goal? You seem to be asking how to put a particular methodology into practice without indicating what the result above and beyond your planned methodology should be. It's important to ask this, since you may or may not be using the simplest, most effective way of doing what you want, and without knowing what that functional goal is, we can't give you the best advice.

dlin

unread,
Apr 8, 2013, 1:03:33 AM4/8/13
to golan...@googlegroups.com
Kevin,

I want to read network bytes into structs. And print them out with my formatter.

So, Char is used to print out bytes array as "ABC".
I left byte array to print out as [ 65, 66,67]

Do you have any better suggestion, could you give me some code to demo best practice?

I know I may do it on wrong way.

On Monday, April 8, 2013 12:21:58 PM UTC+8, Kevin Gillette wrote:
Some questions:

Why do you need to re-type byte as Char? By doing so, you're making []byte (which is a "slice", not an "array") conversion-incompatible with []Char.  I don't see any methods on Char, for example, or any other reason why you'd really need to avoid using byte directly. Also, in Go, it's much more common to type a container, such as `type Chars []byte` rather than an element, as you do with `type byte Char`, and even that isn't often done unless methods are defined on the named type.  Nonetheless, you can initialize []Char from a string by doing: []Char("the string")

Just want to separate output 

You cannot initialize a byte-array (or Char-array) with a fixed length from a string. Usually that does not come up as an issue, since for constant immutable data, strings are preferably used. When you really need to initialize an array, either the way you're doing it, element by element in an array literal, or slicing it and using copy (or doing something in a loop) are the only real means of initialization.
 
I wish there is a compile time decide array instead of run time io.Copy  (Maybe it is none)

reflect, while not necessarily slower than in other reflective languages, is much slower than not using reflection. That said, fmt uses reflection in all but the easy cases, and for output, it's reasonably fast enough.

See reflect.Kind, and the reflect.Type and reflect.Value Kind method. You can check that against the constant reflect.Array to see if something is an array, and use reflect.Type's Elem method to get the element type for an array, slice, chan, etc. You can compare the returned element type for equality with reflect.TypeOf(Char(0)) to see if the element type is a Char, without needing to do any string manipulation.
I'll try later, thanks. 

Kevin Gillette

unread,
Apr 8, 2013, 2:16:14 AM4/8/13
to golan...@googlegroups.com
How I'd implement that in your case would depend on how many array sizes you'd be dealing with. If it only were even 4, then the following would do:

type Char4 [4]byte
func (c Char4) String() string { return string(c[:]) }

Otherwise, the tricky part is that to do this sort of thing with full flexibility (such as responding to %#v and %v appropriately), you'd essentially need to reimplement fmt and expose that functionality as a fmt.Formatter. If you decide to limit yourself to just %v, for example, the task gets somewhat simpler.

In a general sense, it sounds like what you want would be something where a named element type can determine the output style of an unnamed array/slice that contains it, but there's not really anything like that in Go. If byte were not actually an "alias" of uint8, and instead were treated as containing character data in its default fmt'd representation, then that'd solve the issue too.

Most people would live with this by either accepting the default representation, or using strings or slices to hold the content in unexported fields, mediating access through length-validating value-setting methods (thus the length requirement is still reasonably preserved across package boundaries).

A partial implementation of a very limited case: <http://play.golang.org/p/vTNbJJO1u_>. To do anything useful as described above, you'd want to look at fmt.Formatter.

Yves Junqueira

unread,
Apr 8, 2013, 2:50:17 AM4/8/13
to dlin, golang-nuts


On Apr 8, 2013 5:46 AM, "dlin" <dli...@gmail.com> wrote:
>
> As I know google plans to close google reader.  So, I post the question to stackoverflow too.
>

Just note that Google Reader != Google Groups.

dlin

unread,
Apr 8, 2013, 3:14:18 AM4/8/13
to golan...@googlegroups.com
Kevin, thanks.

Your code explain it well.
And, I can do it, just implement the structs for loop things.
Reply all
Reply to author
Forward
0 new messages