Menu
CoddyTech

整合所有内容

本课属于 Coddy GO 学习旅程的“逻辑与流程”单元。第 50 课,共 68 课。

challenge icon

挑战

简单

通过创建一个综合的主程序,整合你在前几课中构建的所有功能,完成库存管理系统。这个最终挑战将库存初始化、库存检查、商品添加、库存更新和报告生成整合到一个完整的命令行界面中,并通过菜单进行导航。

你将收到 3 个输入:

  • 一个字符串,其中包含初始库存数据,格式为 "product1:price1:quantity1,product2:price2:quantity2,product3:price3:quantity3"(例如,"Laptop:999.99:5,Mouse:25.50:15,Keyboard:75.00:8")
  • 一个字符串,其中包含一系列菜单操作,格式为 "operation1,operation2,operation3",操作可以是 "check"、"add"、"update"、"report" 或 "exit"(例如,"check,add,update,report,exit")
  • 一个字符串,其中包含操作参数,格式为 "param1|param2|param3",每个参数对应同一位置的操作(例如,"Mouse|Monitor:299.99:10|Laptop:5|full,10")

你的任务是:

  1. 使用前几课中的同一个 Product 结构体,其中包含 Price(float64)和 Quantity(int)字段
  2. 解析第一个输入,并使用已有商品数据初始化库存映射
  3. 显示系统启动消息:
    • "=== INVENTORY MANAGEMENT SYSTEM ==="
    • "System initialized with [number_of_products] products"
    • "Starting interactive session..."
  4. 解析第二个输入,获取要执行的操作序列
  5. 解析第三个输入,获取每个操作的参数
  6. 按顺序处理每个操作,显示操作标题并执行相应操作:
    • 对于 "check":显示 "--- STOCK CHECK ---",并检查指定商品的库存
    • 对于 "add":显示 "--- ADD ITEM ---",并添加指定商品
    • 对于 "update":显示 "--- UPDATE STOCK ---",并更新指定商品的库存
    • 对于 "report":显示 "--- GENERATE REPORT ---",并生成指定报告
    • 对于 "exit":显示 "--- SYSTEM EXIT ---",并显示退出信息
  7. 实现 checkStock 函数,像前几课一样返回数量和错误
  8. 实现 addNewItem 函数,像前几课一样添加商品并返回错误
  9. 实现 updateStock 函数,像前几课一样更新数量并返回错误
  10. 实现 generateReport 函数,打印下方 "report" 操作所描述的报告
  11. 对于 "check" 操作:
    • 使用参数作为要检查的商品名称
    • 显示:"Checking stock for: [product_name]"
    • 如果找到:"Stock level: [quantity] units"
    • 如果未找到:"Product not found in inventory"
  12. 对于 "add" 操作:
    • 按 "product_name:price:quantity" 格式解析参数
    • 显示:"Adding new product: [product_name]"
    • 如果成功:"Product added successfully"
    • 如果失败:"Failed to add product: [error_message]",其中错误为 "product already exists"
  13. 对于 "update" 操作:
    • 按 "product_name:change" 格式解析参数
    • 显示:"Updating stock for: [product_name]"
    • 如果成功且 change 为零或正数:"Added [change] units. New stock: [new_quantity]"
    • 如果成功且 change 为负数:"Removed [absolute_change] units. New stock: [new_quantity]"
    • 如果失败:"Update failed: [error_message]",错误可能是 "product not found",或者新数量小于 0 时的 "insufficient stock"
  14. 对于 "report" 操作:
    • 按 "report_type,threshold" 格式解析参数,其中 report_type 为 "low" 或 "full",threshold 为整数
    • 显示:"Generating [report_type] report with threshold [threshold]"
    • 然后按字母顺序打印报告中的商品:
      • 对于 "low":先显示 "=== LOW REPORT ===",再显示 "Products with stock below [threshold]:",然后为数量低于阈值的每件商品显示 "- [name]: [quantity] units (Price: $[price])"
      • 对于 "full":先显示 "=== FULL REPORT ===",再显示 "Complete inventory (minimum threshold: [threshold]):",然后为每件商品显示 "- [name]: [quantity] units @ $[price] each [OK]";如果数量低于阈值,则用 [LOW STOCK] 替代 [OK]
  15. 对于 "exit" 操作:
    • 显示最终库存统计信息:
      • "Final inventory status:"
      • "Total products: [total_products]"
      • "Total items: [total_items]"
      • "Total value: $[total_value]"
    • 显示:"Session completed successfully"
    • 显示:"Thank you for using the Inventory Management System"
  16. 每次操作后(exit 除外),显示:"Operation completed. Continuing to next operation..."

使用 strings 包拆分输入字符串,使用 strconv 包将字符串转换为数字,使用 errors 包处理错误,使用 fmt 包格式化输出,并使用 sort 包按字母顺序排序。所有价格和值都保留 2 位小数。这个挑战将展示如何创建一个完整的交互式系统,把多个功能组件整合为连贯的用户体验,并妥善处理错误和管理状态。

亲手试试

package main

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

type Product struct {
	Price    float64
	Quantity int
}

func generateReport(inventory map[string]Product, reportType string, threshold float64) {
	// Display report header
	switch reportType {
	case "full":
		fmt.Println("=== FULL INVENTORY REPORT ===")
	case "low_stock":
		fmt.Println("=== LOW STOCK REPORT ===")
	case "high_value":
		fmt.Println("=== HIGH VALUE REPORT ===")
	}

	// Calculate general statistics
	totalProducts := len(inventory)
	totalItems := 0
	totalValue := 0.0
	
	for _, product := range inventory {
		totalItems += product.Quantity
		totalValue += product.Price * float64(product.Quantity)
	}
	
	averagePrice := totalValue / float64(totalItems)

	// Display general 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)
	fmt.Printf("Average Product Price: $%.2f\n", averagePrice)

	// Filter products based on report type
	var filteredProducts []string
	for name, product := range inventory {
		switch reportType {
		case "full":
			filteredProducts = append(filteredProducts, name)
		case "low_stock":
			if product.Quantity <= int(threshold) {
				filteredProducts = append(filteredProducts, name)
			}
		case "high_value":
			productValue := product.Price * float64(product.Quantity)
			if productValue >= threshold {
				filteredProducts = append(filteredProducts, name)
			}
		}
	}

	// Sort filtered products alphabetically
	sort.Strings(filteredProducts)

	// Display filtered products section header
	switch reportType {
	case "full":
		fmt.Println("All Products:")
	case "low_stock":
		fmt.Printf("Products with stock ≤ %.0f:\n", threshold)
	case "high_value":
		fmt.Printf("Products with value ≥ $%.2f:\n", threshold)
	}

	// Display filtered products
	filteredItems := 0
	filteredValue := 0.0
	for _, name := range filteredProducts {
		product := inventory[name]
		productValue := product.Price * float64(product.Quantity)
		fmt.Printf("- %s: $%.2f × %d = $%.2f\n", name, product.Price, product.Quantity, productValue)
		filteredItems += product.Quantity
		filteredValue += productValue
	}

	// Display filtered statistics
	fmt.Println("Filtered Results:")
	fmt.Printf("Products shown: %d\n", len(filteredProducts))
	fmt.Printf("Items in filtered products: %d\n", filteredItems)
	fmt.Printf("Value of filtered products: $%.2f\n", filteredValue)

	// Find most and least expensive products
	var mostExpensiveName, leastExpensiveName string
	var mostExpensivePrice, leastExpensivePrice float64
	first := true
	
	var sortedNames []string
	for name := range inventory {
		sortedNames = append(sortedNames, name)
	}
	sort.Strings(sortedNames)
	
	for _, name := range sortedNames {
		product := inventory[name]
		if first {
			mostExpensiveName = name
			mostExpensivePrice = product.Price
			leastExpensiveName = name
			leastExpensivePrice = product.Price
			first = false
		} else {
			if product.Price > mostExpensivePrice {
				mostExpensiveName = name
				mostExpensivePrice = product.Price
			}
			if product.Price < leastExpensivePrice {
				leastExpensiveName = name
				leastExpensivePrice = product.Price
			}
		}
	}

	fmt.Println("Price Analysis:")
	fmt.Printf("Most expensive: %s at $%.2f\n", mostExpensiveName, mostExpensivePrice)
	fmt.Printf("Least expensive: %s at $%.2f\n", leastExpensiveName, leastExpensivePrice)

	// Find highest and lowest stock products
	var highestStockName, lowestStockName string
	var highestStock, lowestStock int
	first = true
	
	for _, name := range sortedNames {
		product := inventory[name]
		if first {
			highestStockName = name
			highestStock = product.Quantity
			lowestStockName = name
			lowestStock = product.Quantity
			first = false
		} else {
			if product.Quantity > highestStock {
				highestStockName = name
				highestStock = product.Quantity
			}
			if product.Quantity < lowestStock {
				lowestStockName = name
				lowestStock = product.Quantity
			}
		}
	}

	fmt.Println("Stock Analysis:")
	fmt.Printf("Highest stock: %s with %d units\n", highestStockName, highestStock)
	fmt.Printf("Lowest stock: %s with %d units\n", lowestStockName, lowestStock)

	// Inventory health assessment
	lowStockCount := 0
	highStockCount := 0
	highValueCount := 0
	
	for _, product := range inventory {
		if product.Quantity <= 5 {
			lowStockCount++
		}
		if product.Quantity > 20 {
			highStockCount++
		}
		productValue := product.Price * float64(product.Quantity)
		if productValue >= 500.0 {
			highValueCount++
		}
	}

	fmt.Printf("Low stock items (≤5): %d\n", lowStockCount)
	fmt.Printf("High stock items (>20): %d\n", highStockCount)
	fmt.Printf("High value items (≥$500): %d\n", highValueCount)

	// Report completion
	fmt.Println("Report generated successfully")
	fmt.Printf("Threshold applied: %.2f\n", threshold)
}

func main() {
	var inventoryData string
	var reportConfig string
	fmt.Scanln(&inventoryData)
	fmt.Scanln(&reportConfig)

	// Parse inventory data
	inventory := make(map[string]Product)
	if inventoryData != "" {
		products := strings.Split(inventoryData, ",")
		for _, productStr := range products {
			parts := strings.Split(productStr, ":")
			name := parts[0]
			price, _ := strconv.ParseFloat(parts[1], 64)
			quantity, _ := strconv.Atoi(parts[2])
			inventory[name] = Product{Price: price, Quantity: quantity}
		}
	}

	// Parse report configuration
	configParts := strings.Split(reportConfig, ",")
	reportType := configParts[0]
	threshold, _ := strconv.ParseFloat(configParts[1], 64)

	// Generate report
	generateReport(inventory, reportType, threshold)
}

逻辑与流程中的所有课

自己练习: Go 在线编译器