Golang替代Python的pprint.pformat方法

Golang替代Python的pprint.pformat方法 我正在将Python CLI用Go语言重写,以便利用我想使用的网络效应。我面临的一个挑战是,似乎找不到Python的pprint.pformat的替代品。

我知道有go-spew,但这个项目似乎已经停止维护了,因为它甚至没有go.mod文件。

我也知道fmt.Printf,但用它来重建相同的用户体验将比我预期的要费事得多。


更多关于Golang替代Python的pprint.pformat方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

感谢您的建议!我认为这基本满足了我的需求,因此本主题可以视为已解决。

我知道 JSON 编码器,但我认为它与美化打印是不同的用例,因为编码器会相当大地改变输出。而使用美化打印,对象的内部表示得以保留。

更多关于Golang替代Python的pprint.pformat方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果你想输出格式美观的 JSON,可以随时使用 MarshalIndent

图标

json package - encoding/json - Go Packages

Package json implements encoding and decoding of JSON as defined in RFC 7159.

详情请参阅此 StackOverflow 回答。如果你希望拥有更多控制权,就必须使用反射(类似于你链接的那个包的做法)。下面这个包看起来也很有趣:

图标

pretty package - github.com/kr/pretty - Go Packages

Package pretty provides pretty-printing for Go values.

在Go语言中,虽然没有直接等同于Python pprint.pformat 的内置方法,但可以通过标准库和第三方库实现类似的功能。以下是几种解决方案:

1. 使用标准库 encoding/json

对于JSON格式的可读输出,可以使用json.MarshalIndent

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    data := map[string]interface{}{
        "name": "John",
        "age": 30,
        "address": map[string]interface{}{
            "street": "123 Main St",
            "city": "Boston",
        },
        "hobbies": []string{"reading", "gaming", "coding"},
    }
    
    // 类似pprint.pformat的格式化输出
    formatted, _ := json.MarshalIndent(data, "", "  ")
    fmt.Println(string(formatted))
}

2. 使用 fmt.Printf%#v 格式符

对于调试目的,%#v 可以输出Go语法表示的值:

package main

import "fmt"

type Person struct {
    Name    string
    Age     int
    Address struct {
        Street string
        City   string
    }
}

func main() {
    p := Person{
        Name: "Alice",
        Age:  25,
    }
    p.Address.Street = "456 Oak Ave"
    p.Address.City = "Seattle"
    
    // 输出Go语法表示
    fmt.Printf("%#v\n", p)
}

3. 使用 go-spew(虽然无go.mod但功能完整)

尽管没有go.mod,但go-spew仍然可以工作:

package main

import (
    "github.com/davecgh/go-spew/spew"
)

func main() {
    complexData := []map[string]interface{}{
        {
            "id":   1,
            "data": []int{1, 2, 3, 4, 5},
        },
        {
            "id":   2,
            "data": []string{"a", "b", "c"},
        },
    }
    
    // 使用spew.Dump(类似pprint)
    spew.Dump(complexData)
    
    // 获取格式化字符串(类似pformat)
    formatted := spew.Sdump(complexData)
    fmt.Println(formatted)
}

4. 使用 k8s.io/klog/v2PrettyPrint

如果你不介意引入k8s的库:

package main

import (
    "fmt"
    "k8s.io/klog/v2"
)

func main() {
    data := struct {
        Users []string
        Count int
    }{
        Users: []string{"user1", "user2", "user3"},
        Count: 3,
    }
    
    // 使用klog的格式化
    formatted := klog.PrettyPrint(data)
    fmt.Println(formatted)
}

5. 自定义格式化函数

创建自己的pformat函数:

package main

import (
    "encoding/json"
    "fmt"
    "reflect"
    "strings"
)

func pformat(v interface{}, indent string) string {
    return formatValue(reflect.ValueOf(v), indent, 0)
}

func formatValue(v reflect.Value, indent string, depth int) string {
    switch v.Kind() {
    case reflect.Struct:
        var parts []string
        parts = append(parts, "{\n")
        for i := 0; i < v.NumField(); i++ {
            fieldName := v.Type().Field(i).Name
            fieldValue := formatValue(v.Field(i), indent, depth+1)
            parts = append(parts, 
                strings.Repeat(indent, depth+1)+
                fieldName+": "+fieldValue+",\n")
        }
        parts = append(parts, strings.Repeat(indent, depth)+"}")
        return strings.Join(parts, "")
        
    case reflect.Slice, reflect.Array:
        var parts []string
        parts = append(parts, "[\n")
        for i := 0; i < v.Len(); i++ {
            elem := formatValue(v.Index(i), indent, depth+1)
            parts = append(parts, 
                strings.Repeat(indent, depth+1)+elem+",\n")
        }
        parts = append(parts, strings.Repeat(indent, depth)+"]")
        return strings.Join(parts, "")
        
    case reflect.Map:
        var parts []string
        parts = append(parts, "{\n")
        iter := v.MapRange()
        for iter.Next() {
            key := formatValue(iter.Key(), indent, depth+1)
            value := formatValue(iter.Value(), indent, depth+1)
            parts = append(parts, 
                strings.Repeat(indent, depth+1)+
                key+": "+value+",\n")
        }
        parts = append(parts, strings.Repeat(indent, depth)+"}")
        return strings.Join(parts, "")
        
    default:
        return fmt.Sprintf("%v", v.Interface())
    }
}

func main() {
    data := map[string]interface{}{
        "name": "test",
        "values": []int{1, 2, 3},
    }
    
    fmt.Println(pformat(data, "  "))
}

对于大多数用例,encoding/jsonMarshalIndent 提供了最接近 pprint.pformat 的功能,特别是处理嵌套数据结构时。如果需要在CLI中保持与Python版本相似的用户体验,建议使用JSON格式化输出或实现自定义的格式化函数。

回到顶部