Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Go 如何减少与从JSON解组动态类型并发送到相关通道相关的重复代码?_Go_Design Patterns - Fatal编程技术网

Go 如何减少与从JSON解组动态类型并发送到相关通道相关的重复代码?

Go 如何减少与从JSON解组动态类型并发送到相关通道相关的重复代码?,go,design-patterns,Go,Design Patterns,考虑下面的示例,它接受一条JSON消息,该消息最终被解组为几种可能的类型。如何减少或删除与添加其他事件类型相关的样板代码 package main import ( "encoding/json" "fmt" ) const input = ` { "type": "hello", "event": { "name": "Picard" } } ` type EventEnvelope struct { Type stri

考虑下面的示例,它接受一条JSON消息,该消息最终被解组为几种可能的类型。如何减少或删除与添加其他事件类型相关的样板代码


package main

import (
    "encoding/json"
    "fmt"
)

const input = `
{
    "type": "hello",
    "event": {
        "name": "Picard"
    }
}
`

type EventEnvelope struct {
    Type  string
    Event interface{}
}

type EventHello struct {
    Name string
}

type EventHowdy struct {
    Name string
}

type Display struct {
    formal  chan EventHello
    western chan EventHowdy
}

func newDisplay() *Display {
    return &Display{
        formal:  make(chan EventHello),
        western: make(chan EventHowdy),
    }
}

func (display *Display) run() {
    for {
        select {
        case formal := <-display.formal:
            fmt.Println("Hello", formal.Name)
        case western := <-display.western:
            fmt.Println("Howdy", western.Name)
        }
    }
}

func main() {
    var event json.RawMessage
    env := EventEnvelope{
        Event: &event,
    }
    if err := json.Unmarshal([]byte(input), &env); err != nil {
        fmt.Print(err)
    }

    display := newDisplay()
    go display.run()
    events(display, event, env.Type)
}

func events(display *Display, raw json.RawMessage, event string) {
    switch event {
    case "hello":
        hello := EventHello{}
        if err := json.Unmarshal(raw, &hello); err != nil {
            fmt.Println(err)
        } else {
            display.formal <- hello
        }
    case "howdy":
        howdy := EventHowdy{}
        if err := json.Unmarshal(raw, &howdy); err != nil {
            fmt.Println(err)
        } else {
            display.western <- howdy
        }
    default:
        fmt.Println("No event handler")
    }

}

包干管
进口(
“编码/json”
“fmt”
)
常量输入=`
{
“类型”:“你好”,
“事件”:{
“名称”:“Picard”
}
}
`
类型EventEnvelope结构{
类型字符串
事件接口{}
}
输入EventHello结构{
名称字符串
}
类型EventHowdy结构{
名称字符串
}
类型显示结构{
正式的chan Event你好
西区陈伟迪酒店
}
func newDisplay()*显示{
返回和显示{
正式:make(chan EventHello),
西部:制作(chan EventHowdy),
}
}
func(显示*显示)运行(){
为了{
挑选{

案例形式:=您可以使用类型工厂:

var types map[string]func() interface{} {"hello":func() interface{} {return &EventHello{}}, 
    "howdy": func() interface{} {return &EventHowdy{}}}
工厂可用于使用其名称创建类型的新实例。您可以向这些类型添加新函数,以便它们可以选择自己的通道:

type sender interface {
   send(Display)
}

func (e EventHello) send(d Display) {
   d.formal<-e
}

感谢您优雅的解决方案!
type sender interface {
   send(Display)
}

func (e EventHello) send(d Display) {
   d.formal<-e
}
func events(display *Display, raw json.RawMessage, event string) {
   evInstance:=types[event]()
   if err := json.Unmarshal(raw, evInstance); err != nil {
       fmt.Println(err)
   } else {
       evInstance.(sender).send(display)
   }
}