当前位置: 首页 > 面试题库 >

如何有效地更新两个结构的值

吕越彬
2023-03-14
问题内容

我有以下代码,该代码分析YAML文件,并且需要匹配一个结构的值external并更新该internal结构的type属性。

例如,这是yaml文件(为简单起见翻译为bin)和正确解析的内容

package main

import (
    "fmt"
    "gopkg.in/yaml.v2"
    "log"
)

//internal config model for parsing

type InternalModel struct {
    models []Model2 `yaml:"models"`
}

type Model2 struct {
    Name   string `yaml:"name"`
    Type   string `yaml:"type"`
    Target string `yaml:"target"`
}

var internal_config = []byte(`
 models:
   - name: myapp
     type: app1
     target: ./

   - name: myapp2
     type: app2
     target: ./
`)

type ExternalConfig struct {
    Landscape Zone `yaml:"Landscape"`
}

type Zone struct {
    Zone   string  `yaml:"zone"`
    Models []Model `yaml:"models"`
}

type Model struct {
    AppType     string `yaml:"app-type"`
    ServiceType string `yaml:"service-type"`
}


var external_config = []byte(`
Landscape:
  zone: zone1
  models:
    - app-type: app1
      service-type: GCP
    - app-type: app2
      service-type: AMAZON
  zone: zone2
  models:
    - app-type: app3
      service-type: AZURE
    - app-type: app4Í
      service-type: HEROKU
`)

func main() {

    // This is the internal config which needs updated

    internalConfiglYaml := InternalModel{}

    err := yaml.Unmarshal([]byte(internal_config), &internalConfiglYaml)
    if err != nil {
        log.Fatalf("error in model internalConfiglYaml: %v", err)
    }
    //fmt.Printf("%+v\n", internalConfiglYaml)

    //--------------------------Second config file-----------------------//
    //This is the external config yaml

    extConfigYaml := ExternalConfig{}

    err = yaml.Unmarshal([]byte(external_config), &extConfigYaml)
    if err != nil {
        log.Fatalf("error in model extConfigYaml: %v", err)
    }
    fmt.Printf("%+v\n", extConfigYaml)

    landscape := "zone1"

    modifiedConfig := ConvertTypes(internalConfiglYaml, extConfigYaml, landscape)

    fmt.Printf("%+v\n", modifiedConfig)

}

func ConvertTypes(int_cfg InternalModel, ext_config ExternalConfig, landscape string) (out_cfg InternalModel) {

    for _, module := range int_cfg.models {

        switch module.Type {
        case "app1":
            //here I hard-coded the value "GCP" but it should come from the yaml struct after parsing
            module.Type = "GCP" // should be something like ext_config.models.service-type when the key in the struct
        case "app2":
            //here I hard-coded the value "AMAZON" but it should come from the yaml struct after parsing
            module.Type = "AMAZON"

        }
    }

    return int_cfg
}

//At the end what I need to do is to get the internal yaml file to be changed to the following struct
//The changes are when the type=app-type I need to modify the type in the internal config, here its GCP and ruby

//internal_config_after_changes := []byte(`
//
//
//models:
// - name: myapp
//   type: GCP
//   target: ./
//
// - name: myapp2
//   type: AMAZON
//   target: ./
//
//
//`)

最后,我需要做的是将内部yaml文件更改为上面的结构internal_config_after_changes 。更改是type=app- type我需要 修改type值时internal_config,这里是从app1to GCPapp2toamazon

问题在于第二个循环,我应该使用它来迭代external_config和匹配的值,我不确定如何以有效的方式将它们组合在一起。


问题答案:

Golang常见问题解答介绍了有关地图和切片的指针:

映射和切片值的行为类似于指针:它们是包含指向基础映射或切片数据的指针的描述符。复制地图或切片值不会复制其指向的数据。复制接口值将复制存储在接口值中的事物。如果接口值包含一个结构,则复制接口值将复制该结构。如果接口值包含一个指针,则复制接口值将复制该指针,但不会复制它指向的数据。

遍历内部模型切片时,ConvertType实际上是在创建[]Models其值的切片副本。由于该原因,Type不会更改原始结构的值。

for _, module := range int_cfg.models{}

上面的代码段正在创建的副本int_cfg.models{}

索引切片模型以指向切片模型的确切基础数组,以将值更改为:

package main

import (
    "fmt"
    "log"
    "strings"

    "gopkg.in/yaml.v2"
)

//internal config model for parsing

type InternalModel struct {
    Models []Model2 `yaml:"models"`
}

type Model2 struct {
    Name   string `yaml:"name"`
    Type   string `yaml:"type"`
    Target string `yaml:"target"`
}

var internal_config = []byte(`
  models:
    - name: myapp
      type: app1
      target: ./

    - name: myapp2
      type: app2
      target: ./
`)

type ExternalConfig struct {
    Landscape []Zone `yaml:"Landscape"`
}

type Zone struct {
    Zone   string  `yaml:"zone"`
    Models []Model `yaml:"models"`
}

type Model struct {
    AppType     string `yaml:"app-type"`
    ServiceType string `yaml:"service-type"`
}

var external_config = []byte(`
Landscape:
  - zone: zone1
    models:
     - app-type: app1
       service-type: GCP
     - app-type: app2
       service-type: AMAZON
  - zone: zone2
    models:
     - app-type: app3
       service-type: AZURE
     - app-type: app4Í
       service-type: HEROKU
`)

func main() {

    //This is the internal config which needs to be update

    internalConfiglYaml := InternalModel{}

    err := yaml.Unmarshal(internal_config, &internalConfiglYaml)
    if err != nil {
        log.Fatalf("error in model internalConfiglYaml: %v", err)
    }
    fmt.Printf("%+v\n", internalConfiglYaml)

    //--------------------------Second config file-----------------------//
    //This is the external config yaml

    extConfigYaml := ExternalConfig{}
    // var response interface{}

    err = yaml.Unmarshal(external_config, &extConfigYaml)
    if err != nil {
        log.Fatalf("error in model extConfigYaml: %v", err)
    }
    fmt.Printf("%+v\n", extConfigYaml)

    landscape := "zone1"

    modifiedConfig := ConvertTypes(&internalConfiglYaml, extConfigYaml, landscape)

    fmt.Printf("%+v\n", modifiedConfig)

}

// ConvertTypes for changing the intConfig struct types
func ConvertTypes(int_cfg *InternalModel, ext_config ExternalConfig, landscape string) (out_cfg *InternalModel) {

    for _, module := range ext_config.Landscape {
        if module.Zone == landscape {
            for i, value := range module.Models {
                switch strings.Compare(value.AppType, int_cfg.Models[i].Type) {
                case 0:
                    //here I hard-coded the value "GCP" but it should come from the yaml struct after parsing
                    int_cfg.Models[i].Type = value.ServiceType // should be something like ext_config.models.service-type when the key in the struct
                default:
                }
            }
        }
    }

    return int_cfg
}

如果检查以上代码片段,您还将认识到我已经更改了结构。

type InternalModel struct {
    models []Model2 `yaml:"models"`
}

首字母大写以使其可导出为:

type InternalModel struct {
    Models []Model2 `yaml:"models"`
}

由于struct InternalModelis
unexportable,因此字段model无法解析提供的internal_configyaml,从而导致在解组yaml后导致空的[]
slice数据。

我注意到的另一件事是您再次将字节转换为字节。没有必要。

err := yaml.Unmarshal([]byte(internal_config), &internalConfiglYaml)

所以我将其更改为:

err := yaml.Unmarshal(internal_config, &internalConfiglYaml)

因为internal_config已经[]byte在全局变量中使用字节声明。



 类似资料:
  • 问题内容: 如何合并两个保持BST属性的二叉搜索树? 如果我们决定从一棵树中取出每个元素并将其插入到另一个元素中,则此方法的复杂度将为,其中是我们已拆分的树的节点数(例如),是的结点数。另一棵树(例如)。此操作后,只有一个具有节点。 我的问题是:我们能做得比好吗? 问题答案: 纳夫的答案还有更多细节: 将BST展平为排序列表为O(N) 它只是整个树上的“有序”迭代。 两者都做O(n1 + n2)

  • 我有两个火花数据帧。我想基于第二个更新第一个。 数据流1 df2 我想更新第一个数据帧(df1),如下所示 我不知道如何加入嵌套结构中的数据

  • 问题内容: 我有两个具有以下结构的json文件 和 如您所见,json和演员表的内部结构相同。我想将这些json文件解编为相同的golang结构。但是我不能为相同的struct元素提供两个名称标签(广播和电影)。我想要类似的东西 在这种情况下,Detail可以同时解析演员和电影。 这是我当前的代码 但它仅适用于第一个标签“ cast”,并在json包含电影的情况下给出nill。 提前致谢。 问题答

  • 问题内容: 是否有一个将Enum对象用作键的Map集合的更有效,更专业的实现? 问题答案: 在偶然偶然发现Java API的答案后,我才了解到这一点。如果您有使用枚举作为键的映射,请确保使用EnumMap。这是非常简单, 很多 更高效:

  • 我正在尝试消化包,我似乎很难理解。 我正在阅读包文档,并试图实现它,以便边做边学。这是我读过的课文: 中间操作返回一个新流。他们总是懒惰;执行filter()之类的中间操作实际上并不执行任何筛选,而是创建一个新流,在遍历该流时,该流包含与给定谓词匹配的初始流的元素。管道源的遍历直到执行管道的终端操作才开始。 总体而言,旧的模式要比高效得多。所以,这里又有更多的问题: 我误解了什么吗? 如果我理解正

  • 问题内容: 使用此DataFrame,当等于零时如何有条件地将其设置为0 ? 换句话说,在DataFrame上说ColumnA = x然后ColumnB = y否则ColumnB = ColumnB的正确方法是什么? 问题答案: