【问题标题】:Golang switch between structsGolang 在结构之间切换
【发布时间】:2015-08-31 16:30:12
【问题描述】:

我是 golang 新手,我正在尝试创建一个函数,根据它所使用的结构,将使用 Sprintf 返回格式化字符串

type Name struct {
    Title string
    First string
    Last  string
}

type Location struct {
    Street string
    City   string
    State  string
    Zip    string
}

func Merge(m interface{}) string {
    switch m.(type) {
    case *Location:
        return fmt.Sprintf("%s \n %s, %s %s", m.(*Location).Street, m.(*Location).City, m.(*Location).State, m.(*Location).Zip)
    case *Name:
        return fmt.Sprintf("%s. %s %s", m.(*Name).Title, m.(*Name).First, m.(*Name).Last)
    }
    return "Not Applicable"
}

fmt.Println(Merge(Location))

我收到了来自我的PrintLn 的“Not Applicable”消息。在代码的一个版本中,我相信消息是“out of index”。

【问题讨论】:

  • 您没有将*Location 传递给Merge;这就是为什么你得到“不适用”的原因。此外,您可能需要考虑为您的类型实现 fmt.Stringer
  • 感谢蒂姆的建议。您能否详细说明我将如何使用 fmt.Stringer? println(merge())) 行是我所拥有的简化。我的实际线路是 fmt.Println(Merge(servicesA.Users[0].Location))
  • servicesA.Users[0].Location的类型是什么:Location*Location?此外,您可能会发现有用的 %v%+vSprintf
  • 感谢您的评论,科斯蒂亚。它应该只是位置。当我尝试删除函数中的指针(*Location to Location)并运行它时,我得到了这个:panic: interface conversion: interface is main.Location not *main.Location

标签: struct go interface switch-statement


【解决方案1】:

在您的示例中,您试图将结构本身传递给函数,而不是结构的实例。当我运行您的代码时,它不会编译。不过我同意上面的 cmets,确保每个结构都满足 fmt.Stringer 接口会更好地处理。

fmt.Stringer interface

您的代码的固定版本:

package main

import "fmt"

type Name struct {
    Title string
    First string
    Last  string
}

type Location struct {
    Street string
    City   string
    State  string
    Zip    string
}

func Merge(m interface{}) string {
    switch m.(type) {
    case Location:
        return fmt.Sprintf("%s \n %s, %s %s", m.(Location).Street, m.(Location).City, m.(Location).State, m.(Location).Zip)
    case Name:
        return fmt.Sprintf("%s. %s %s", m.(Name).Title, m.(Name).First, m.(Name).Last)
    }
    return "Not Applicable"
}

func main() {
    l := Location{
        Street: "122 Broadway",
        City: "New York",
        State: "NY",
        Zip: "1000",
    }
    fmt.Println(Merge(l))
}

使用 fmt.String 的版本:

package main

import "fmt"

type Name struct {
    Title string
    First string
    Last  string
}

func (n *Name) String() string {
    return fmt.Sprintf("%s. %s %s", n.Title, n.First, n.Last)
}

type Location struct {
    Street string
    City   string
    State  string
    Zip    string
}

func (l *Location) String() string {
    return fmt.Sprintf("%s \n %s, %s %s", l.Street, l.City, l.State, l.Zip)
}

func main() {
    l := &Location{
        Street: "120 Broadway",
        City:   "New York",
        State:  "NY",
        Zip:    "1000",
    }
    fmt.Println(l)

    n := &Name{
        Title: "Mr",
        First: "Billy",
        Last:  "Bob",
    }
    fmt.Println(n)
}

【讨论】:

  • 谢谢你,汤姆!这是一个很好的解释!当我输入 Println 函数时,我也忘记在 Merge 函数中包含对 *Location 的 & 引用。我的最终 Println 方法是这样的: fmt.Println(Merge(&servicesA.Users[0].Location)) 在更改并查看您的代码之后,它按我的预期工作。再次感谢汤姆。
  • 如果您要使用类型开关,则不应在案例主体中使用类型断言。例如。 play.golang.org/p/Wh9mAr4xzi.
  • OP 提到的例子是一个简化,如果你有多种类型都希望有一个共同的行为,那么使用接口是很常见的(fmt.Stringer 仅适用于字符串表示整个类型)。例如。也许像play.golang.org/p/xq3a0RcbFa
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 2015-05-22
  • 2018-01-04
  • 2013-12-31
  • 2013-09-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多