Зациклить на кусок структуры и обновить значение - PullRequest
0 голосов
/ 27 февраля 2019

Я получаю данные из источника 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 я хочу обновить фрагмент структур из источника A некоторыми данными из источника B.

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 срезу структур?

1 Ответ

0 голосов
/ 27 февраля 2019

Каждый раз, когда вы имеете дело со значениями, которые, как вы знаете, вам нужно изменить, лучше, по крайней мере, на мой взгляд, использовать указатели.Они сделают вашу жизнь проще.

Поэтому вместо:

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
}

В качестве альтернативы, если вы хотите продолжать использовать типы без указателей, вы можете напрямую изменять значения, на которые ссылаютсяпо срезу путем индексации в нем.

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
}
...