如何将Go打印枚举字段设为字符串?

Igo*_*tis 11 enums go

您使用"%v"打印实现Stringer的枚举,它将打印其字符串值.如果在结构中声明相同的枚举并使用"%v"打印结构,它将打印枚举的数值.有没有办法打印枚举字段的字符串值?

示例(https://play.golang.org/p/AP_tzzAZMI):

package main

import (
    "fmt"
)

type MyEnum int

const (
    Foo MyEnum = 1
    Bar MyEnum = 2
)

func (e MyEnum) String() string {
    switch e {
    case Foo:
        return "Foo"
    case Bar:
        return "Bar"
    default:
        return fmt.Sprintf("%d", int(e))
    }
}

type MyStruct struct {
    field MyEnum
}

func main() {
    info := &MyStruct{
        field: MyEnum(1),
    }
    fmt.Printf("%v\n", MyEnum(1))
    fmt.Printf("%v\n", info)
    fmt.Printf("%+v\n", info)
    fmt.Printf("%#v\n", info)
}
Run Code Online (Sandbox Code Playgroud)

打印:

Foo
&{1}
&{field:1}
&main.MyStruct{field:1}
Run Code Online (Sandbox Code Playgroud)

Sar*_*lai 11

你需要创建字段exported,即你可以将结构声明为

type MyStruct struct {
    Field MyEnum
}
Run Code Online (Sandbox Code Playgroud)

这是一个带有exportedunexported字段的示例程序

package main

import (
    "fmt"
)

type MyEnum int

const (
    Foo MyEnum = 1
    Bar MyEnum = 2
)

func (e MyEnum) String() string {
    switch e {
    case Foo:
        return "Foo"
    case Bar:
        return "Bar"
    default:
        return fmt.Sprintf("%d", int(e))
    }
}

type MyStruct struct {
    Field1 MyEnum
    field2 MyEnum
}

func main() {
    info := &MyStruct{
        Field1: MyEnum(1),
        field2: MyEnum(2),
    }
    fmt.Printf("%v\n", MyEnum(1))
    fmt.Printf("%v\n", info)
    fmt.Printf("%+v\n", info)
    fmt.Printf("%#v\n", info)
}
Run Code Online (Sandbox Code Playgroud)

产量

Foo
&{Foo 2}
&{Field1:Foo field2:2}
&main.MyStruct{Field1:1, field2:2}
Run Code Online (Sandbox Code Playgroud)

这是播放链接:https://play.golang.org/p/7knxM4KbLh

  • 如果你想'%#v'也显示你需要实现'fmt.GoStringer'的字符串 (3认同)

ape*_*ena 11

使用stringer。它是 Golang 工具链的一个组成部分,专门为此任务而设计。


Cyb*_*sam 6

我将使用此方法稍微扩展已接受的答案:

type MyEnum int

const (
    Foo MyEnum = iota
    Bar
)

func (me MyEnum) String() string {
    return [...]string{"Foo", "Bar"}[me]
}

// ...

fmt.Println(Foo, Bar)  // Prints: Foo Bar
Run Code Online (Sandbox Code Playgroud)

上面的代码假设枚举值从 0 开始,这很有效,因为方法 String 中数组中的第一个元素可以直接被枚举值引用。

但是原始问题中的第一个枚举值的值为 1。我们可以相应地修改它的方法。

const (
    Foo MyEnum = iota + 1
    Bar
)

func (me MyEnum) String() string {
    return [...]string{"", "Foo", "Bar"}[me]
}
Run Code Online (Sandbox Code Playgroud)

这是播放链接:https : //play.golang.org/p/6pmyVlsAeV2

  • 是的。`[...] string { "a", "b", "c" } [n]` 和 `[] string { "a", "b", "c" } [n]` 给出相同的结果结果。区别在于前者创建一个数组,后者创建一个切片。这声明了一个切片:`a := string { "a", "b", "c" }`。这声明了一个 2 的数组:`b := [3]string{ "a", "b", "c" }`。这与前面的相同,只是你让 Go 编译器为你计算元素:`b := [...]string{ "a", "b", "c" } `。参考:https://blog.golang.org/slices-intro (3认同)
  • 这样,您将在每次调用该函数时创建一个切片。将此映射定义为全局对象或使用开关。否则,如果有大量线程尝试使用枚举对象的字符串,内存将会崩溃。 (2认同)