pointers - 遍历一片结构并更新值

标签 pointers go struct slice

我正在从源 A 获取数据并将其存储在一片结构中,如下所示:

type ProductPrice struct {
    Type          string
    Sku           string
    UnitPrice     string
    PriceList     string
    standardPrice string
    specialPrice  string
    specialStart  string
    specialEnd    string
    pricingUnit   string
    categoryCode  string
    isOnSpecial   bool
}

func getProductPricesFromDatabase(instance string) []ProductPrice {
    rows, err := myDBConnection.Query(// My query here)

    if err != nil {
        log.Fatal("There was an issue with the query for product price: ", err)
    }

    defer rows.Close()

    var productPrices []ProductPrice

    for rows.Next() {
        var product = ProductPrice{}
        err := rows.Scan(
            &product.Type,
            &product.Sku,
            &product.standardPrice,
            &product.specialPrice,
            &product.specialStart,
            &product.specialEnd,
            &product.pricingUnit,
            &product.PriceList,
            &product.categoryCode,
        )
        if err != nil {
            log.Fatal("product price scan error: ", err)
        }

        productPrices = append(productPrices, product)
    }

    return productPrices
}

然后我从源 B 获取一些数据并将其存储在一片结构中,如下所示:

type ContractProductPrice struct {
    CustID                 string
    PriceBy                string
    AppliesTo              string
    PriceList              string
    StartDate              string
    EndDate                string
    PricingAdjustmentType  string
    PricingAdjustmentValue string
    UseLowest              string
}

func getContractProductPricesFromDatabase(instance string) []ContractProductPrice {
    rows, err := myDBConnection.Query(// My query here)

    if err != nil {
        log.Fatal("There was an issue with the query for contract product price: ", err)
    }

    defer rows.Close()

    var contractProductPrices []ContractProductPrice

    for rows.Next() {
        var product = ContractProductPrice{}
        err := rows.Scan(
            &product.CustID,
            &product.PriceBy,
            &product.AppliesTo,
            &product.PriceList,
            &product.StartDate,
            &product.EndDate,
            &product.PricingAdjustmentType,
            &product.PricingAdjustmentValue,
            &product.UseLowest,
        )
        if err != nil {
            log.Fatal("contract product price scan error: ", err)
        }
        contractProductPrices = append(contractProductPrices, product)
    }

    return contractProductPrices
}

从源 B 获取数据后,我想用源 B 的一些数据更新源 A 的结构 slice 。

productPrices := getProductPricesFromDatabase(instance)
contractProductPrices := getContractProductPricesFromDatabase(instance)

processedProductPrices := processProductPricesFromDatabase(productPrices, contractProductPrices)

func processProductPricesFromDatabase(productPrices []ProductPrice, contractProductPrices []ContractProductPrice) []ProductPrice {
    // Loop over contact prices and update relevant product prices
    for _, contractPrice := range contractProductPrices {
        for _, product := range productPrices {
            if contractPrice.AppliesTo == product.Sku {
                product.UnitPrice = contractPrice.PricingAdjustmentValue
            }
        }
    }

    return productPrices
}

但是,运行后,processedProductPrices 中的单价仍然为空。

通过搜索,我了解了问题所在; Go 是按值传递的,所以我没有更新原始内存地址,所以值没有改变。 但是,我不理解/不知道我需要更改什么来解决这个问题,因为我正在使用一片结构而不是一个更简单的数字/字符串片等示例。

如何更新 productPrices 以便在我返回它时,processedProductPrices 等于更新后的 productPrices 结构 slice ?

最佳答案

任何时候当您处理您知道需要修改的值时,至少在我看来,最好使用指针。它们会让您的生活更轻松。

所以代替:

func getProductPricesFromDatabase(instance string) []ProductPrice {
    // ...
    var productPrices []ProductPrice

    for rows.Next() {
        var product = ProductPrice{}

        // ...
    }    
    return productPrices
}

我建议您将代码重构为:

func getProductPricesFromDatabase(instance string) []*ProductPrice {
    // ...
    var productPrices []*ProductPrice

    for rows.Next() {
        var product = new(ProductPrice)

        // ...
    }    
    return productPrices
}

现在对 getContractProductPricesFromDatabase 执行相同操作,最后将参数类型更新到您的 processProductPricesFromDatabase 函数:

func processProductPricesFromDatabase(productPrices []*ProductPrice, contractProductPrices []*ContractProductPrice) []*ProductPrice {
    // Loop over contact prices and update relevant product prices
    for _, contractPrice := range contractProductPrices {
        for _, product := range productPrices {
            if contractPrice.AppliesTo == product.Sku {
                product.UnitPrice = contractPrice.PricingAdjustmentValue
            }
        }
    }
    return productPrices
}

作为替代方案,如果您想继续使用非指针类型,您可以通过索引直接修改 slice 引用的值。

func processProductPricesFromDatabase(productPrices []ProductPrice, contractProductPrices []ContractProductPrice) []ProductPrice {
    // Loop over contact prices and update relevant product prices

    for _, contractPrice := range contractProductPrices {

        for i, _ := range productPrices {
            if contractPrice.AppliesTo == productPrices[i].Sku {
                productPrices[i].UnitPrice = contractPrice.PricingAdjustmentValue
            }
        }
    }

    return productPrices
}

关于pointers - 遍历一片结构并更新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54898660/

相关文章:

对 C 中的 "pass by reference"以及何时使用 & 或 * 感到困惑

json - 如何使用 Golang 解码动态 json 对象

去生成 : stringer: invalid operation: has no field or method String

c - 从 (char *) &(struct) 等结构将参数传递给读取函数

c++ - 在函数中填充结构图的最佳方法是什么

c++ - 电话号码列表

C++ 如何在内存中指定一个位置来获取数据?

c - 函数指针的指针值代表什么?

go - 使用 Golang 和 Bootstrap 时表单数据始终为空

c - ‘.’ 标记之前的预期构造函数、析构函数或类型转换