如何用字节数组作为字符串漂亮地打印结构?

时间:2019-08-09 12:19:57

标签: go

我正在尝试从网络数据中解码动态结构,这是简化版本。 FmtA[3]byte,需要打印为字符串。因此,这是我通过定义Bytes3数据类型的愚蠢实现。 如果使用此方法,则应定义Bytes6Bytes4Bytes2

有没有更好的方法将所有字节数组打印为字符串而不是字节数组?

package main                                                                                                                                                           

import "fmt"                                                                    

type Bytes3 [3]byte                                                             
type FmtA struct {                                                            
        Field1 Bytes3                                                           
        Field2 [6]byte                                                          
        Field3 uint8                                                            
}                                                                               
type FmtB struct {                                                            
        Field1 uint16                                                           
        Field2 [4]byte                                                          
        Field3 [2]byte                                                          
}                                                                               

func (b Bytes3) String() string {                                               
        v := [3]byte(b)                                                         
        return string(v[:])                                                     
}                                                                               
func main() {                                                                   
        a := FmtA{[3]byte{'a', 'b', 'c'}, [6]byte{'d', 'e', 'f', 'g', 'h', 'i'},
                36}                                                             
        b := FmtB{42, [4]byte{'a', 'b', 'c', 'd'}, [2]byte{'e', 'f'}}           
        var i interface{}   // simulate the received variable type                                                     
        i = a                                                                   
        fmt.Printf("a=%+v\n", i)                                                
        i = b                                                                   
        fmt.Printf("b=%+v\n", i)                                                
        // Output:                                                              
        // a={Field1:abc Field2:[100 101 102 103 104 105] Field3:36}            
        // b={Field1:42 Field2:[97 98 99 100] Field3:[101 102]}                 
}

1 个答案:

答案 0 :(得分:1)

您可以创建一个实用程序函数,该函数可以采用任何结构,使用反射检查字段并进行相应的格式化(对于不是字节数组,但强制字节数组打印为字符串的字段,请使用默认值)。

例如:

func Struct2String(theStruct interface{}) string {
    reflectV := reflect.ValueOf(theStruct)
    structType := reflectV.Type()
    b := &bytes.Buffer{}
    b.WriteString("{")
    for i := 0; i < reflectV.NumField(); i++ {
        if i > 0 {
            b.WriteString(" ")
        }
        b.WriteString(structType.Field(i).Name)
        b.WriteString(": ")
        fieldValue := reflectV.Field(i)
        fieldType := reflectV.Field(i).Type()
        fieldKind := reflectV.Field(i).Kind()
        if (fieldKind == reflect.Slice || fieldKind == reflect.Array) && fieldType.Elem().Kind() == reflect.Uint8 {
            fmt.Fprintf(b, "%s", fieldValue)
        } else {
            fmt.Fprint(b, fieldValue)
        }
    }
    b.WriteString("}")
    return b.String()
}

在这里您可以看到示例使用在Go游乐场中定义的结构运行:

https://play.golang.org/p/zGZM5S8UMWZ