更新库存数量
本课属于 Coddy GO 学习旅程的“逻辑与流程”单元。第 48 课,共 68 课。
挑战
简单通过实现库存数量更新,并加入全面的验证和错误处理,增强你的库存管理系统。本挑战基于前面课中的功能,让你能够修改现有商品的数量,同时防止可能导致库存变成负数的无效操作。
你会收到两个输入:
- 一个字符串,包含现有库存数据,格式为
"product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3"(例如,"Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8") - 一个字符串,包含库存更新请求,格式为
"product1:change1,product2:change2,product3:change3",其中变更量可以是正整数或负整数(例如,"Mouse:10,Tablet:-5,Keyboard:-3")
你的任务是:
- 使用前面课程中的同一个
Product结构体,包含Price(float64)和Quantity(int)字段 - 通过按逗号分割第一个输入,获取每个现有商品条目
- 对于每个现有商品条目,按冒号分割,获取商品名称、价格和数量
- 将价格字符串转换为 float64,将数量字符串转换为 int
- 使用现有商品数据创建并填充
inventory映射 - 创建一个名为
updateStock的函数,它接收库存映射、商品名称和数量变更作为参数,并返回一个错误:- 如果商品不存在于库存中,返回错误,错误消息为
"product not found: [product_name]" - 如果数量变更会导致库存变成负数(当前数量 + 变更量 < 0),返回错误,错误消息为
"insufficient stock: cannot reduce [product_name] by [absolute_change_value], only [current_quantity] available" - 如果更新有效,则修改库存中该商品的数量并返回 nil
- 如果商品不存在于库存中,返回错误,错误消息为
- 通过按逗号分割第二个输入,获取库存更新请求列表
- 对于每个更新请求,按冒号分割,获取商品名称和数量变更
- 将数量变更字符串转换为 int
- 显示更新过程标题:
"Processing Stock Updates:" - 对于每个更新请求,调用
updateStock函数并显示结果:- 如果没有错误且变更量为正数:
"[product_name]: Added [change] units - New stock: [new_quantity]" - 如果没有错误且变更量为负数:
"[product_name]: Removed [absolute_change_value] units - New stock: [new_quantity]" - 如果没有错误且变更量为零:
"[product_name]: No change - Current stock: [current_quantity]" - 如果发生错误:
"[product_name]: Update failed - [error_message]"
- 如果没有错误且变更量为正数:
- 统计并显示更新数据:
"Update Summary:""Updates processed: [total_number_of_updates_processed]""Updates successful: [number_of_successful_updates]""Updates failed: [number_of_failed_updates]"
- 按商品名称的字母顺序显示更新后的库存:
"Updated Inventory:"- 对于每件商品:
"- [product_name]: $[price] (Stock: [quantity])"
- 计算并显示最终库存数据:
"Final Inventory Statistics:""Total Products: [total_number_of_products_in_inventory]""Total Items in Stock: [sum_of_all_quantities]""Total Inventory Value: $[sum_of_price_times_quantity_for_all_products]"
- 列出所有更新失败的商品:
- 如果有更新失败:
"Failed updates: [comma_separated_list_of_failed_product_names]" - 如果没有更新失败:
"All stock updates were processed successfully"
- 如果有更新失败:
使用 strings 包分割输入字符串,使用 strconv 包将字符串转换为数字,使用 errors 包创建错误消息,使用 fmt 包进行格式化输出,并使用 sort 包按字母顺序排列商品名称。所有价格和库存总价值都保留 2 位小数。本挑战演示如何在全面验证和错误处理的帮助下,安全地修改现有数据并防止无效操作。
亲手试试
package main
import (
"errors"
"fmt"
"sort"
"strconv"
"strings"
)
type Product struct {
Price float64
Quantity int
}
func addNewItem(inventory map[string]Product, productName string, price float64, quantity int) error {
if _, exists := inventory[productName]; exists {
return errors.New("product already exists: " + productName)
}
inventory[productName] = Product{Price: price, Quantity: quantity}
return nil
}
func main() {
var existingInventory string
var newProducts string
fmt.Scanln(&existingInventory)
fmt.Scanln(&newProducts)
inventory := make(map[string]Product)
// Parse existing inventory
existingItems := strings.Split(existingInventory, ",")
for _, item := range existingItems {
parts := strings.Split(item, ":")
name := parts[0]
price, _ := strconv.ParseFloat(parts[1], 64)
quantity, _ := strconv.Atoi(parts[2])
inventory[name] = Product{Price: price, Quantity: quantity}
}
// Parse new products to add
newItems := strings.Split(newProducts, ",")
fmt.Println("Adding New Items:")
itemsProcessed := 0
itemsAdded := 0
itemsRejected := 0
var rejectedProducts []string
for _, item := range newItems {
parts := strings.Split(item, ":")
name := parts[0]
price, _ := strconv.ParseFloat(parts[1], 64)
quantity, _ := strconv.Atoi(parts[2])
itemsProcessed++
err := addNewItem(inventory, name, price, quantity)
if err != nil {
fmt.Printf("%s: Failed to add - %s\n", name, err.Error())
itemsRejected++
rejectedProducts = append(rejectedProducts, name)
} else {
fmt.Printf("%s: Successfully added - $%.2f (Stock: %d)\n", name, price, quantity)
itemsAdded++
}
}
// Addition summary
fmt.Println("Addition Summary:")
fmt.Printf("Items processed: %d\n", itemsProcessed)
fmt.Printf("Items added: %d\n", itemsAdded)
fmt.Printf("Items rejected: %d\n", itemsRejected)
// Display updated inventory in alphabetical order
fmt.Println("Updated Inventory:")
var productNames []string
for name := range inventory {
productNames = append(productNames, name)
}
sort.Strings(productNames)
totalProducts := 0
totalItems := 0
totalValue := 0.0
for _, name := range productNames {
product := inventory[name]
fmt.Printf("- %s: $%.2f (Stock: %d)\n", name, product.Price, product.Quantity)
totalProducts++
totalItems += product.Quantity
totalValue += product.Price * float64(product.Quantity)
}
// Final inventory statistics
fmt.Println("Final Inventory Statistics:")
fmt.Printf("Total Products: %d\n", totalProducts)
fmt.Printf("Total Items in Stock: %d\n", totalItems)
fmt.Printf("Total Inventory Value: $%.2f\n", totalValue)
// List rejected products
if len(rejectedProducts) > 0 {
fmt.Printf("Rejected products: %s\n", strings.Join(rejectedProducts, ","))
} else {
fmt.Println("All new products were added successfully")
}
}逻辑与流程中的所有课
自己练习: Go 在线编译器