1

我有一个定义如下的结构

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 失败,我不知道如何以不同的方式打印它。

4

1 回答 1

2

创建一个以为基础类型的新类型,并在值传递给 之前对其进行转换。创建一个新类型将把它从它的所有方法中剥离,包括方法:WallpaperInfofmt.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}

请参阅相关问题:

在 UnmarshalJSON 函数中调用 json.Unmarshal 而不会导致堆栈溢出

于 2020-10-11T16:09:52.577 回答