如何漂亮地打印字节数组和字符数组?

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

How to pretty print byte array and char array?

问题

在下面的代码中,我试图编写一个Txt()函数来漂亮地打印出我的结构。在完整的代码中,包含以下几个小问题:

  1. 如何通过字符串初始化字符数组的一行代码(第47行)。
  2. 如何加快检查字符类型而不使用字符串函数(第29、30行)。
  3. 如何将字符数组打印为字符串(第32行)。
  4. 如何将字符打印为字符串,可能使用Sprintf("%c"),但它非常慢(第34行)。

完整代码请参考:http://play.golang.org/p/nUsg_qbufP

type Char byte
type THeader struct {
    Ver int8 // 将显示为1
    Tag Char // 将显示为'H'
}
type TBody struct {
    B1 [3]byte  // 将显示为"[0,0,0]"
    B2 [4]Char // 将显示为"ABCD"
}
func Txt(t interface{}) (s string) {
    val := reflect.ValueOf(t)
    typ := val.Type()
    fields := typ.NumField()
    for i := 0; i < fields; i++ {
        sf := typ.Field(i)
        valfld := val.Field(i)
        vType := valfld.Type()
        s += sf.Name + ":" + vType.String() + ":"
        if strings.HasSuffix(vType.String(), "Char") {
            if strings.HasPrefix(vType.String(), "[") {
                v, ok := valfld.Interface().([4]Char)
                s += fmt.Sprint(ok, v) + "\n"
            } else {
                s += fmt.Sprint(valfld.Interface()) + "\n"
            }
        } else {
            s += fmt.Sprint(valfld.Interface()) + "\n"
        }
    }
    return
}

func main() {
    th := THeader{1, 'H'}
    fmt.Printf("%#v\n", th)
    // tb := TBody{B2: [10]Char("ABCD")}
    tb := TBody{B2: [4]Char{'A', 'B', 'C', 'D'}}
    fmt.Printf("%#v\n", tb)
    fmt.Print("Txt(th):\n", Txt(th), "\n")
    fmt.Print("Txt(tb):\n", Txt(tb), "\n")

}
英文:

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

type Char byte
type THeader struct {
	Ver int8 // will show 1
	Tag Char // will show &#39;H&#39;
}
type TBody struct {
	B1 [3]byte  // will show &quot;[0,0,0]&quot;
	B2 [4]Char // will show &quot;ABCD&quot;
}    
func Txt(t interface{}) (s string) {
  val := reflect.ValueOf(t)
  typ := val.Type()
  fields := typ.NumField()
  for i := 0; i &lt; fields; i++ {
    sf := typ.Field(i)
	valfld := val.Field(i)
	vType := valfld.Type()
	s += sf.Name + &quot;:&quot; + vType.String() + &quot;:&quot;
	if strings.HasSuffix(vType.String(), &quot;Char&quot;) {
	  if strings.HasPrefix(vType.String(), &quot;[&quot;) {
	    v, ok := valfld.Interface().([4]Char)
	    s += fmt.Sprint(ok, v) + &quot;\n&quot;
  	  } else {
	    s += fmt.Sprint(valfld.Interface()) + &quot;\n&quot;
      }
	} else {
	  s += fmt.Sprint(valfld.Interface()) + &quot;\n&quot;
	}
  }
  return
}

func main() {
	th := THeader{1, &#39;H&#39;}
	fmt.Printf(&quot;%#v\n&quot;, th)
	//	tb := TBody{B2: [10]Char(&quot;ABCD&quot;)}
	tb := TBody{B2: [4]Char{&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;}}
	fmt.Printf(&quot;%#v\n&quot;, tb)
	fmt.Print(&quot;Txt(th):\n&quot;, Txt(th), &quot;\n&quot;)
	fmt.Print(&quot;Txt(tb):\n&quot;, Txt(tb), &quot;\n&quot;)

}

答案1

得分: 1

这段代码应该可以回答除了你的第一个问题之外的所有问题,因为函数无法返回长度不同的数组,而Go语言也没有初始化动态派生大小数组的功能。对于这些问题,你需要使用切片。其余的代码可以使用惯用的Go语言方式解决,使用Stringer接口而不需要反射。

package main

import (
	"fmt"
)

type Char byte
type CharSlice []Char
type ByteSlice []byte

func (s CharSlice) String() string {
	ret := ""
	for _, b := range s {
		ret += fmt.Sprintf("%c", b)
	}
	ret += ""
	return ret
}

func (s ByteSlice) String() string {
	return fmt.Sprintf("%v", []byte(s))
}

type THeader struct {
	Ver int8 // will show 1
	Tag Char // will show 'H'
}

func (t THeader) String() string {
	return fmt.Sprintf("{ Ver: %d, Tag: %c}", t.Ver, t.Tag)
}

type TBody struct {
	B1 [3]byte // will show "[0,0,0]"
	B2 [4]Char // will show "ABCD"
}

func (t TBody) String() string {
	return fmt.Sprintf("{ B1: %s, B2: %s", ByteSlice(t.B1[:]), CharSlice(t.B2[:]))
}

func main() {
	th := THeader{1, 'H'}
	fmt.Printf("%#v\n", th)
	tb := TBody{B2: [4]Char{'A', 'B', 'C', 'D'}}
	fmt.Printf("%#v\n", tb)
	fmt.Printf("Txt(th):\n%s\n", th)
	fmt.Printf("Txt(tb):\n%s\n", tb)

}
英文:

This code should answer all except for your 1'st questions which is impossible since a function can't return arrays of varying length and Go has no facility to initialize an array of dynamically derived sizes. You need slices for those. The rest of the code is solveable using idiomatic go with the Stringer interface and no reflection required.

package main

import (
	&quot;fmt&quot;
)

type Char byte
type CharSlice []Char
type ByteSlice []byte

func (s CharSlice) String() string {
	ret := &quot;\&quot;&quot;
	for _, b := range s {
		ret += fmt.Sprintf(&quot;%c&quot;, b)
	}
	ret += &quot;\&quot;&quot;
	return ret
}

func (s ByteSlice) String() string {
	return fmt.Sprintf(&quot;%v&quot;, []byte(s))
}

type THeader struct {
	Ver int8 // will show 1
	Tag Char // will show &#39;H&#39;
}

func (t THeader) String() string {
	return fmt.Sprintf(&quot;{ Ver: %d, Tag: %c}&quot;, t.Ver, t.Tag)
}

type TBody struct {
	B1 [3]byte // will show &quot;[0,0,0]&quot;
	B2 [4]Char // will show &quot;ABCD&quot;
}

func (t TBody) String() string {
	return fmt.Sprintf(&quot;{ B1: %s, B2: %s&quot;, ByteSlice(t.B1[:]), CharSlice(t.B2[:]))
}

func main() {
	th := THeader{1, &#39;H&#39;}
	fmt.Printf(&quot;%#v\n&quot;, th)
	tb := TBody{B2: [4]Char{&#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;}}
	fmt.Printf(&quot;%#v\n&quot;, tb)
	fmt.Printf(&quot;Txt(th):\n%s\n&quot;, th)
	fmt.Printf(&quot;Txt(tb):\n%s\n&quot;, tb)

}

huangapple
  • 本文由 发表于 2013年4月8日 11:40:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/15870887.html
匿名

发表评论

匿名网友

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

确定