【问题标题】:Assigning a struct using similar struct of pointers in Go在 Go 中使用类似的指针结构分配结构
【发布时间】:2017-11-21 16:50:23
【问题描述】:

我有两个相似的结构,我想将一个分配给另一个。 第一个“设备”是用来匹配数据库的结构。第二个“JsonEquipment”是解析JSON数据的辅助结构。

这是一个例子:

type Equipment struct {
    ID         uint
    CategoryID uint
    Ip         string
    Login      string
    Password   string
}

type JsonEquipment struct {
    ID           *uint
    Category     *string
    Ip           *string
    Login        *string
    Password     *string
}

指针用于检查 JSON 中是否存在该字段。更多信息:How to recognize void value and unspecified field when unmarshaling in Go?

所以目前我创建了一个带有许多“if”的函数来检查并分配给设备,但我想知道是否有更好、更清洁的解决方案。

func CreateEquipment(item JsonEquipment) (Equipment) {
    e := Equipment{}

    if item.ID != nil && !previousEquipment.Auto { // Is the field present & not automatic equipment
        e.ID = *item.ID
    }

    if item.Ip != nil { // Is the field present ?
        e.Ip = *item.Ip
    }

    if item.Login != nil { // Is the field present ?
        e.Login = *item.Login
    }

    [...]
    return e
}

我希望你能理解这个想法。

这个问题类似于 Assign struct with another struct 但由于指针不同而不同 => 非指针结构

【问题讨论】:

  • 为什么不直接使用接口?你为什么还要检查这些值是否不为零?
  • 所以让我把流程弄清楚。 1)你得到一个json格式的设备; 2)您要检查设备的json是否具有您需要的所有值; 3) 使用Equipment 结构将其写入数据库。
  • 为了避免大量ifs,您可以为每种可能的类型组合创建简单的辅助函数,例如string/*stringint/*intint64/*int64play.golang.org/p/i1c4D6lwY2
  • @DenysSéguret 如果我不检查,我会得到一个指针错误;为什么我需要?因为当我更新设备时,我需要区分我想设置空值(例如 IP)的情况,我只想保留以前的值(未分配)
  • @Mihailo 是的,你明白了!

标签: pointers go struct go-gorm


【解决方案1】:

我不确定是否正确理解了您的问题,但这样的事情是否能胜任:

type Equipment struct {
    ID         uint
    CategoryID uint
    Ip         string
    Login      string
    Password   string
}

func main(){
    // Grabing the equipment.
    equips := getEquipment()

    // Checking each equipment for its validity.
    for _, e := range equips {
        if (e.isValid()) {
            fmt.Println(e, "is OK!")
        } else {
            fmt.Println(e, "is NOT OK!")
        }
    }
}

// getEquipment fetches the json from the file.
func getEquipment() (e []Equipment) {
    raw, err := ioutil.ReadFile("./equipment.json")
    if err != nil {
        fmt.Println(err.Error())
        os.Exit(1)
    }

    json.Unmarshal(raw, &e)

    return 
}

// isValid checks if the equipment has all the required fields.
func (e *Equipment) isValid() bool {
    if (e.Ip == "" || e.Login == "") { // You might add more validation rules
        return false
    }

    return true
}

它非常简单,但我不确定您还想在这里做什么。
这样你就有了一个 Equipment 结构,并且不需要包含指针的另一个“副本”。

你可以试试这个代码here

【讨论】:

  • 通过这些验证,我将无法将“”设置为 IP、登录等。这就是我需要指针的原因
  • 此验证是完全可选的。我写它是因为我觉得您认为 Equipment 缺少字段是无效的。您实际上在数据库中是否有一个现有的Equipment,并且您想使用作为 json 提供的新 Equipment 来更新它。但是在更新期间,您只想更改具有JsonEquipment 值的字段吗?对吗?
  • 是的,没错。但我也会根据给定的 JSON 文件插入和删除
【解决方案2】:

编辑

我在下面所做的工作有效,但没有达到我的预期。 实际上,我的第一个代码是检查空字段和未指定字段之间差异的唯一解决方案。

以下是差异的演示: https://play.golang.org/p/3tU6paM9Do


首先感谢大家的帮助,尤其是@Mihailo。

我最终做的是让我的模型结构没有指针,即:

type Equipment struct {
    ID         uint
    CategoryID uint
    Ip         string
    Login      string
    Password   string
}

我使用了一个具有模型结构指针的 JSON 辅助结构,即

type JsonHelper struct {
    Equipments    []*Equipment
    [Add other structures here]
}

最后我使用 JsonHelper 结构解析了 JSON:

func ParseJSON(inputPath string) JsonHelper {
    // Read configuration file
    content, err := ioutil.ReadFile(inputPath)
    if err != nil {
        log.Println("Error:", err)
    }

    var input JsonHelper

    // Parse JSON from the configuration file
    err = json.Unmarshal(content, &input)
    if err != nil {
        log.Print("Error: ", err)
    }

    return input
}

HTH

【讨论】:

    猜你喜欢
    • 2021-11-26
    • 2013-12-13
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 2020-05-02
    • 2021-04-01
    相关资源
    最近更新 更多