为了账号安全,请及时绑定邮箱和手机立即绑定

创建需要其他重复逻辑作为先决条件的函数(干净的代码)

创建需要其他重复逻辑作为先决条件的函数(干净的代码)

Go
慕码人8056858 2023-04-17 14:58:50
我有以下我需要的 yaml 文件parse(解析按预期工作)并且需要data从 yaml 文件内容中提供一个应该由以下解耦函数公开的文件我需要提供以下功能(这里是其中一些功能的示例,需要更多具有相同模式的功能......)获取应用程序()获取服务()GetApp(应用名称)GetServiceForApp(应用名称)这是代码(有效...)var DMZ = []byte(`applications:  - name: app1    type: php    src: /app1    host: us    use:       - redis      - mysql  - name: app2    type: rust    src: /app2    host: eu    use:       - mongo      - mysql  - name: app3    type: golang    src: /app3    host: us    use:       - postgress      - mysqlservices:  - name: mongo    type: db    host: us  - name: mysql    type: db    host: eu  - name: postgress    type: db    host: us  - name: redis    type: db    host: us   `)
查看完整描述

3 回答

?
慕勒3428872

TA贡献1848条经验 获得超6个赞

解析指针类型结构值中的值,该值将存储指针指向的结构中的值。然后 Create 方法接收所有你想从中获取结构内应用程序或服务值的方法。


在所有方法中使用指针接收器,您将能够访问在解析 yaml 时更新的原始结构。


创建一个指向该结构的空实例的指针并将其作为方法接收器传递。然后在解组中访问该结构以更新原始结构中的 yaml 数据。通过使用指向方法的指针接收器访问原始结构的值来访问每个函数中更新的结构。


package main


import (

    "fmt"

    "log"


    yaml "gopkg.in/yaml.v2"

)


var dmz = []byte(`

applications:

  - name: app1

    type: php

    src: /app1

    host: us

    use: 

      - redis

      - mysql


  - name: app2

    type: rust

    src: /app2

    host: eu

    use: 

      - mongo

      - mysql


  - name: app3

    type: golang

    src: /app3

    host: us

    use: 

      - postgress

      - mysql



services:

  - name: mongo

    type: db

    host: us


  - name: mysql

    type: db

    host: eu


  - name: postgress

    type: db

    host: us


  - name: redis

    type: db

    host: us   

`)


type DMZ struct {

    Applications []*Applications `yaml:"applications,omitempty"`

    Services     []*Services     `yaml:"services,omitempty"`

}


type Applications struct {

    Name string

    Type string

    Src  string `yaml:"src,omitempty"`

    use  []Use  `yaml:"use,omitempty"`

}

type Services struct {

    Name string

    Type string

    Host string `yaml:"host,omitempty"`

}

type Use struct {

    Name string `yaml:"name,omitempty"`

    host string `yaml:"host,omitempty"`

    Type string `yaml:"type,omitempty"`

}


func main() {

    dm := &DMZ{}

    result, err := dm.Parse(dmz)

    dm.getApp("app1")

    if err != nil {

        fmt.Println(err)

    }

    fmt.Println(result)

    fmt.Println(dm.getApp("app2"))

    fmt.Println(dm.GetServiceForApp("mongo"))

}


func (dmz *DMZ) getApps() []*Applications {

    return dmz.Applications

}


func (dmz *DMZ) getServices() []*Services {

    return dmz.Services

}


func (dmz *DMZ) getApp(appname string) *Applications {

    for _, value := range dmz.Applications {

        if appname == value.Name {

            fmt.Println((*value).Name)

            return value

        }

    }

    return nil

}


func (dmz *DMZ) GetServiceForApp(appname string) *Services {

    for _, value := range dmz.Services {

        if appname == value.Name {

            return value

        }

    }

    return nil

}


// Parse file

func (dmz *DMZ) Parse(yamlContent []byte) (out *DMZ, err error) {

    err = yaml.Unmarshal([]byte(yamlContent), &dmz)

    if err != nil {

        log.Fatal("Yaml file is not valid, Error: " + err.Error())

    }

    return dmz, err

}

游乐场上的工作代码


如果你想让你的代码更干净,那么你也可以跳过从 parse 函数返回的结构。由于我们正在传递一个指针类型的接收器并将原始结构更新为:


package main


import (

    "fmt"

    "log"


    yaml "gopkg.in/yaml.v2"

)


var dmz = []byte(`

applications:

  - name: app1

    type: php

    src: /app1

    host: us

    use: 

      - redis

      - mysql


  - name: app2

    type: rust

    src: /app2

    host: eu

    use: 

      - mongo

      - mysql


  - name: app3

    type: golang

    src: /app3

    host: us

    use: 

      - postgress

      - mysql



services:

  - name: mongo

    type: db

    host: us


  - name: mysql

    type: db

    host: eu


  - name: postgress

    type: db

    host: us


  - name: redis

    type: db

    host: us   

`)


type DMZ struct {

    Applications []*Applications `yaml:"applications,omitempty"`

    Services     []*Services     `yaml:"services,omitempty"`

}


type Applications struct {

    Name string

    Type string

    Src  string `yaml:"src,omitempty"`

    use  []Use  `yaml:"use,omitempty"`

}

type Services struct {

    Name string

    Type string

    Host string `yaml:"host,omitempty"`

}

type Use struct {

    Name string `yaml:"name,omitempty"`

    host string `yaml:"host,omitempty"`

    Type string `yaml:"type,omitempty"`

}


func main() {

    dm := &DMZ{}

    dm.Parse(dmz)

    fmt.Println(dm.getApp("app2"))

    fmt.Println(dm.GetServiceForApp("mongo"))

}


func (dmz *DMZ) getApps() []*Applications {

    return dmz.Applications

}


func (dmz *DMZ) getServices() []*Services {

    return dmz.Services

}


func (dmz *DMZ) getApp(appname string) *Applications {

    for _, value := range dmz.Applications {

        if appname == value.Name {

            fmt.Println((*value).Name)

            return value

        }

    }

    return nil

}


func (dmz *DMZ) GetServiceForApp(appname string) *Services {

    for _, value := range dmz.Services {

        if appname == value.Name {

            return value

        }

    }

    return nil

}


// Parse file

func (dmz *DMZ) Parse(yamlContent []byte) {

    if err := yaml.Unmarshal([]byte(yamlContent), &dmz); err != nil {

        log.Fatal("Yaml file is not valid, Error: " + err.Error())

    }

}

我们可以注意到 Parse 函数将变得更加干净,因为我们没有从它返回任何东西,我们只是使用方法 receiver 更新原始结构,这是实现您一直试图实现的目标的更好方法。


您还可以选择通过将 struct 中的方法定义为您尝试为其实现接口的接收器来实现接口:


package main


import (

    "fmt"

    "log"


    yaml "gopkg.in/yaml.v2"

)


type DI interface {

    GetApps() []*Applications

    GetServices() *Services

}


var dmz = []byte(`

applications:

  - name: app1

    type: php

    src: /app1

    host: us

    use: 

      - redis

      - mysql


  - name: app2

    type: rust

    src: /app2

    host: eu

    use: 

      - mongo

      - mysql


  - name: app3

    type: golang

    src: /app3

    host: us

    use: 

      - postgress

      - mysql



services:

  - name: mongo

    type: db

    host: us


  - name: mysql

    type: db

    host: eu


  - name: postgress

    type: db

    host: us


  - name: redis

    type: db

    host: us   

`)


type DMZ struct {

    Applications []*Applications `yaml:"applications,omitempty"`

    Services     []*Services     `yaml:"services,omitempty"`

}


type Applications struct {

    Name string

    Type string

    Src  string `yaml:"src,omitempty"`

    use  []Use  `yaml:"use,omitempty"`

}

type Services struct {

    Name string

    Type string

    Host string `yaml:"host,omitempty"`

}

type Use struct {

    Name string `yaml:"name,omitempty"`

    host string `yaml:"host,omitempty"`

    Type string `yaml:"type,omitempty"`

}


func main() {

    dm := &DMZ{}

    dm.Parse(dmz)

    fmt.Println(dm.getApp("app2"))

    fmt.Println(dm.GetServiceForApp("mongo"))

}


func (dmz *DMZ) GetApps() []*Applications {

    return dmz.Applications

}


func (dmz *DMZ) GetServices() []*Services {

    return dmz.Services

}


func (dmz *DMZ) getApp(appname string) *Applications {

    for _, value := range dmz.Applications {

        if appname == value.Name {

            fmt.Println((*value).Name)

            return value

        }

    }

    return nil

}


func (dmz *DMZ) GetServiceForApp(appname string) *Services {

    for _, value := range dmz.Services {

        if appname == value.Name {

            return value

        }

    }

    return nil

}


// Parse file

func (dmz *DMZ) Parse(yamlContent []byte) {

    if err := yaml.Unmarshal([]byte(yamlContent), &dmz); err != nil {

        log.Fatal("Yaml file is not valid, Error: " + err.Error())

    }

}

笔记:


泛型很方便,但它们的代价是类型系统和运行时的复杂性。我们还没有找到一种设计,让价值与复杂性成正比,尽管我们继续考虑它。同时,Go 的内置映射和切片,加上使用空接口构造容器(显式拆箱)的能力,意味着在许多情况下,即使不那么流畅,也可以编写实现泛型能够实现的功能的代码。


查看完整回答
反对 回复 2023-04-17
?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

您可以定义一个接口并在结构中提供实现


type DMZI interface {

    GetApps() []Application

    GetService() []Service

    GetApp(name string) (Application, error)

    GetServiceForApp(name string) ([]string, error)

}


type DMZ struct {

    Application []Application `yaml:"applications,omitempty"`

    Service     []Service     `yaml:"services,omitempty"`

}


func (dmz DMZ) GetApps() []Application {

    return dmz.Application

}


func (dmz DMZ) GetService() []Service {

    return dmz.Service

}


func (dmz DMZ) GetApp(name string) (Application, error) {

    for _, app := range dmz.Application {

        if app.Name == name {

            return app, nil

        }

    }

    return Application{}, fmt.Errorf("Did not find application with name %s", name)

}


func (dmz DMZ) GetServiceForApp(name string) ([]string, error) {

    app, err := dmz.GetApp(name)

    if err != nil {

        return []string{}, err

    }

    return app.Use, nil

}


type Application struct {

    Name string

    Type string

    Src  string   `yaml:"src,omitempty"`

    Use  []string `yaml:"use,omitempty"`

}

type Service struct {

    Name string

    Type string

    Host string `yaml:"host,omitempty"`

}


// Parse file

func Parse(yamlContent []byte) (out DMZI, err error) {

    dmz := DMZ{}

    err = yaml.Unmarshal([]byte(yamlContent), &dmz)

    if err != nil {

        fmt.Println("Yaml file is not valid, Error: " + err.Error())

    }

    return dmz, err

}

因此,您可以调用返回接口上的方法,例如


fmt.Printf("Apps : %+v\n", dmz.GetApps())

fmt.Printf("Service : %+v\n", dmz.GetService())

更新


评论中要求的主要方法


func main() {

    dmz, err := Parse([]byte(ymlStr))

    if err != nil {

        panic(err)

    }

    fmt.Printf("Apps : %+v\n", dmz.GetApps())

    fmt.Printf("Service : %+v\n", dmz.GetService())

}

将打印


Apps : [{Name:app1 Type:php Src:/app1 Use:[redis mysql]} {Name:app2 Type:rust Src:/app2 Use:[mongo mysql]} {Name:app3 Type:golang Src:/app3 Use:[postgress mysql]}]

Service : [{Name:mongo Type:db Host:us} {Name:mysql Type:db Host:eu} {Name:postgress Type:db Host:us} {Name:redis Type:db Host:us}]



查看完整回答
反对 回复 2023-04-17
?
慕森卡

TA贡献1806条经验 获得超8个赞

我已经稍微更改了您的代码并完成了我认为您所要求的,即每当您创建 DMZ 的新实例时始终调用“Parse”。这就是您使用Dargo执行此操作的方式。查看底部以了解代码如何将 DMZ 绑定到 ServiceLocator 以及如何获取 DMZ 的新实例

type DMZ struct {

    Applications []*Applications `yaml:"applications,omitempty"`

    Services     []*Services     `yaml:"services,omitempty"`

}


// This method is called every time DMZ is created via the Dargo API

func (dmz *DMZ) DargoInitialize(ioc.Descriptor) error {

    // get ur bytes from... wherever

    Parse(dmz, []byte{})

}


type Applications struct {

    Name string

    Type string

    Src  string `yaml:"src,omitempty"`

    use  []Use  `yaml:"use,omitempty"`

}

type Services struct {

    Name string

    Type string

    Host string `yaml:"host,omitempty"`

}

type Use struct {

    Name string `yaml:"name,omitempty"`

    host string `yaml:"host,omitempty"`

    Type string `yaml:"type,omitempty"`

}


// Parse file

func Parse(dmz *DMZ, yamlContent []byte) (out *DMZ, err error) {

    err = yaml.Unmarshal([]byte(yamlContent), &dmz)

    if err != nil {

        logs.Error("Yaml file is not valid, Error: " + err.Error())

    }

    return dmz, err

}


func useDargo() error {

    locator, err := ioc.CreateAndBind("example", func(binder ioc.Binder) error {

        binder.Bind("DMZ", &DMZ{}).InScope(ioc.PerLookup)

    })

    if err != nil {

        return err

    }


    // This is how you would get your instances of DMZ

    locator.GetDService("DMZ")

}


查看完整回答
反对 回复 2023-04-17
  • 3 回答
  • 0 关注
  • 134 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信