【问题标题】:how to print original go struct in String method如何在 String 方法中打印原始 go struct
【发布时间】:2020-10-12 01:15:46
【问题描述】:

我有一个定义如下的结构

type WallpaperType int

// ...

type WallpaperInfo struct {
    WallpaperType WallpaperType `json:"type"`
    HelpMsg       string        `json:"help"`
    Path          string        `json:"path"`
    ImageColor    color.RGBA    `json:"imageColor"`
}

使用打印这样的结构

winfo := &WallpaperInfo{...}
log.Println(winfo)
log.Printf("%+v\n", winfo)

提供类似的东西

&{Slideshow Wallpaper is a slideshow D:\Images\Wallpapers\autumn-autumn-leaves-blur-close-up-589840.jpg {219 77 66 167}}

&{WallpaperType:Slideshow HelpMsg:Wallpaper is a slideshow Path:D:\Images\Wallpapers\autumn-autumn-leaves-blur-close-up-589840.jpg ImageColor:{R:219 G:77 B:66 A:167}}

我想将它打印为 JSON,所以我为结构实现了 String 方法,如下所示

func (w WallpaperInfo) String() string {
    bytes, err := json.Marshal(w)
    if err != nil {
        return "" // ???
        // this will call the method recursively
        // return fmt.Sprintf("%+v\n", w)
    }
    return string(bytes)
}

万一String()方法出错,

我想打印原始的&{WallpaperType:Slideshow HelpMsg:Wallpaper is a slideshow Path:D:\Images\Wallpapers\autumn-autumn-leaves-blur-close-up-589840.jpg ImageColor:{R:219 G:77 B:66 A:167}}

我尝试返回 fmt.Sprintf("%+v\n", w),但它会递归调用相同的函数。

有什么方法可以返回原始结构格式?因为如果 json 失败,我不知道如何以不同的方式打印它。

【问题讨论】:

    标签: string go struct types


    【解决方案1】:

    创建一个new type,将WallpaperInfo 作为其underlying type,并将convert 的值传递给fmt.Sprintf()。创建新类型会将其从所有方法中剥离,包括 String() 方法:

    func (w WallpaperInfo) String() string {
        bytes, err := json.Marshal(w)
        if err != nil {
            type wi WallpaperInfo
            return fmt.Sprintf("%+v\n", wi(w))
        }
        return string(bytes)
    }
    

    虽然您的类型永远不会返回 JSON 封送错误,但在一般情况下,您可以通过这种方式实现您想要的。

    这是一个故意使 JSON 编组失败的示例,并将回退到原始结构字符串表示:

    type fail int
    
    func (fail) MarshalJSON() ([]byte, error) {
        return nil, errors.New("on-purpose error")
    }
    
    type MyStruct struct {
        F fail
    }
    
    func (m MyStruct) String() string {
        bytes, err := json.Marshal(m)
        if err != nil {
            log.Printf("JSON error: %v", err)
            type ms MyStruct
            return fmt.Sprintf("%+v\n", ms(m))
        }
        return string(bytes)
    }
    

    测试它:

    s := MyStruct{}
    
    log.Println(s)
    log.Printf("%+v\n", s)
    

    哪个会输出(在Go Playground上试试):

    2009/11/10 23:00:00 JSON error: json: error calling MarshalJSON for type main.fail: on-purpose error
    2009/11/10 23:00:00 {F:0}
    
    2009/11/10 23:00:00 JSON error: json: error calling MarshalJSON for type main.fail: on-purpose error
    2009/11/10 23:00:00 {F:0}
    

    查看相关问题:

    Call json.Unmarshal inside UnmarshalJSON function without causing stack overflow

    【讨论】:

      猜你喜欢
      • 2014-11-19
      • 1970-01-01
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 2023-03-21
      • 1970-01-01
      • 2017-12-20
      相关资源
      最近更新 更多