package main import ( "encoding/json" "fmt" "log" "strconv" "strings" "time" ) // KfzVerifyPriceInfo 主结构体 type KfzVerifyPriceInfo struct { Isbn string `json:"isbn"` // ISBN OnSaleCount string `json:"onSaleCount"` // 在售数量 AvgPrice string `json:"avgPrice"` // 平均价格 LastPushTime string `json:"lastPushTime"` // 最后推送时间 Source string `json:"source"` // 来源 Data []BookItem `json:"data"` // 商品列表 } // BookItem 商品项的具体结构 type BookItem struct { Price string `json:"price"` // 价格 "17.01" ShippingFee float64 `json:"shippingFee"` // 运费 0 或 5.8 Condition string `json:"condition"` // 品相 "八五品" ImgBigUrl string `json:"imgBigUrl"` // 图片URL ShopAvgShippingTime string `json:"shopAvgShippingTime"` // 平均发货时间 "10" ShopSuccessOrderRate string `json:"shopSuccessOrderRate"` // 成功率 "90.03" GoodsUrl string `json:"goodsUrl"` // 商品URL "575550/9643470711" Title string `json:"title"` // 标题 GoodsImgCount int `json:"goodsImgCount"` // 图片数量 9 } // ParseRedisData 解析Redis返回的数据 func ParseRedisData(redisData interface{}) (*KfzVerifyPriceInfo, error) { // 将redisData转换为[]interface{}类型 data, ok := redisData.([]interface{}) if !ok { return nil, fmt.Errorf("redis数据格式错误: 期望数组,得到 %T", redisData) } // 检查数组长度 if len(data) < 6 { return nil, fmt.Errorf("redis数据格式错误: 数组长度不足,期望至少6个元素,实际 %d", len(data)) } // 创建结果对象 result := &KfzVerifyPriceInfo{} // 解析ISBN (索引0) if isbn, ok := data[0].(string); ok { result.Isbn = isbn } else { result.Isbn = fmt.Sprintf("%v", data[0]) } // 解析在售数量 (索引2) if onSaleCount, ok := data[2].(string); ok { result.OnSaleCount = onSaleCount } else { result.OnSaleCount = fmt.Sprintf("%v", data[2]) } // 解析平均价格 (索引3) if avgPrice, ok := data[3].(string); ok { result.AvgPrice = avgPrice } else { result.AvgPrice = fmt.Sprintf("%v", data[3]) } // 解析最后推送时间 (索引4) if lastPushTime, ok := data[4].(string); ok { result.LastPushTime = lastPushTime } else { result.LastPushTime = fmt.Sprintf("%v", data[4]) } // 解析来源 (索引5) if source, ok := data[5].(string); ok { result.Source = source } else { result.Source = fmt.Sprintf("%v", data[5]) } // 解析商品列表 (索引1) bookItems, err := parseBookItems(data[1]) if err != nil { return nil, fmt.Errorf("解析商品列表失败: %v", err) } result.Data = bookItems return result, nil } // parseBookItems 解析商品列表 func parseBookItems(items interface{}) ([]BookItem, error) { // 将items转换为[]interface{} itemList, ok := items.([]interface{}) if !ok { return nil, fmt.Errorf("商品列表格式错误: 期望数组,得到 %T", items) } bookItems := make([]BookItem, 0, len(itemList)) for i, item := range itemList { // 每个商品项应该是一个包含9个元素的数组 bookData, ok := item.([]interface{}) if !ok { log.Printf("第%d个商品格式错误: 期望数组,得到 %T", i, item) continue } if len(bookData) < 9 { log.Printf("第%d个商品数据长度不足: 期望至少9个元素,实际 %d", i, len(bookData)) continue } bookItem := BookItem{} // 解析价格 (索引0) if price, ok := bookData[0].(string); ok { bookItem.Price = price } else { bookItem.Price = fmt.Sprintf("%v", bookData[0]) } // 解析运费 (索引1) switch v := bookData[1].(type) { case float64: bookItem.ShippingFee = v case int: bookItem.ShippingFee = float64(v) case string: if f, err := strconv.ParseFloat(v, 64); err == nil { bookItem.ShippingFee = f } default: bookItem.ShippingFee = 0 } // 解析品相 (索引2) if condition, ok := bookData[2].(string); ok { bookItem.Condition = condition } else { bookItem.Condition = fmt.Sprintf("%v", bookData[2]) } // 解析图片URL (索引3) if imgUrl, ok := bookData[3].(string); ok { bookItem.ImgBigUrl = imgUrl } else { bookItem.ImgBigUrl = fmt.Sprintf("%v", bookData[3]) } // 解析平均发货时间 (索引4) if shippingTime, ok := bookData[4].(string); ok { bookItem.ShopAvgShippingTime = shippingTime } else { bookItem.ShopAvgShippingTime = fmt.Sprintf("%v", bookData[4]) } // 解析成功率 (索引5) if successRate, ok := bookData[5].(string); ok { bookItem.ShopSuccessOrderRate = successRate } else { bookItem.ShopSuccessOrderRate = fmt.Sprintf("%v", bookData[5]) } // 解析商品URL (索引6) if goodsUrl, ok := bookData[6].(string); ok { bookItem.GoodsUrl = goodsUrl } else { bookItem.GoodsUrl = fmt.Sprintf("%v", bookData[6]) } // 解析标题 (索引7) if title, ok := bookData[7].(string); ok { bookItem.Title = title } else { bookItem.Title = fmt.Sprintf("%v", bookData[7]) } // 解析图片数量 (索引8) switch v := bookData[8].(type) { case int: bookItem.GoodsImgCount = v case float64: bookItem.GoodsImgCount = int(v) case string: if count, err := strconv.Atoi(v); err == nil { bookItem.GoodsImgCount = count } default: bookItem.GoodsImgCount = 0 } bookItems = append(bookItems, bookItem) } return bookItems, nil } // GetValueFromDB1 当从DB2获取失败时,从DB1的cp85hash中查找对应的key并加1 func GetValueFromDB1(redisClient *RedisClient, originalKey string) (string, error) { // 提取ISBN号(去掉"cp:"前缀) isbn := strings.TrimPrefix(originalKey, "cp:") // 切换到DB1 err := redisClient.SelectDB(1) if err != nil { return "", fmt.Errorf("切换到DB1失败: %v", err) } // 从cp85hash中获取对应的值 hashKey := "cp85" value, err := redisClient.HGet(hashKey, isbn) if err != nil { return "", fmt.Errorf("从cp85hash获取数据失败: %v", err) } log.Println("cp85Isbn:", isbn, "value:", value) // 将值转换为整数并加1 intValue, err := strconv.Atoi(value) if err != nil { return "", fmt.Errorf("值转换失败: %v", err) } newValue := intValue + 1 // 更新hash中的值 err = redisClient.HSet(hashKey, isbn, strconv.Itoa(newValue)) if err != nil { return "", fmt.Errorf("更新cp85hash值失败: %v", err) } log.Printf("成功更新DB1中cp85hash的键 %s,值从 %d 增加到 %d", isbn, intValue, newValue) // 切换回DB2(保持一致性) err = redisClient.SelectDB(2) if err != nil { log.Printf("切换回DB2失败: %v", err) } return "", nil } // 修改您的main函数 func main() { // 自定义配置 config := &RedisConfig{ Addr: "36.212.20.113:7963", Password: "j8nZ4jra2E", DB: 2, PoolSize: 20, MinIdleConns: 10, DialTimeout: 5 * time.Second, ReadTimeout: 3 * time.Second, WriteTimeout: 3 * time.Second, PoolTimeout: 4 * time.Second, } // 使用自定义配置 redisClient := NewRedisClient(config) defer redisClient.Close() // 字符串操作示例 key := "cp:9787040110951" // 获取字符串值 val, err := redisClient.Get(key) if err != nil { log.Printf("从DB2获取失败: %v", err) // 尝试从DB1的cp85hash中查找并加1 newValue, db1Err := GetValueFromDB1(redisClient, key) if db1Err != nil { log.Printf("从DB1获取也失败: %v", db1Err) return } fmt.Printf("从DB1的cp85hash中找到并更新值: %s\n", newValue) return } fmt.Printf("键 %s 的原始值: %s\n", key, val) // 由于Redis返回的是JSON字符串,需要先解析 var redisData interface{} err = json.Unmarshal([]byte(val), &redisData) if err != nil { log.Printf("JSON解析失败: %v", err) return } // 解析为结构体 result, err := ParseRedisData(redisData) if err != nil { log.Printf("解析Redis数据失败: %v", err) return } // 输出解析后的结构体 fmt.Println("\n=== 解析后的数据 ===") fmt.Printf("ISBN: %s\n", result.Isbn) fmt.Printf("在售数量: %s\n", result.OnSaleCount) fmt.Printf("平均价格: %s\n", result.AvgPrice) fmt.Printf("最后推送时间: %s\n", result.LastPushTime) fmt.Printf("来源: %s\n", result.Source) fmt.Printf("商品数量: %d\n", len(result.Data)) // 输出商品列表 for i, item := range result.Data { fmt.Printf("\n--- 商品 %d ---\n", i+1) fmt.Printf(" 价格: %s\n", item.Price) fmt.Printf(" 运费: %.2f\n", item.ShippingFee) fmt.Printf(" 品相: %s\n", item.Condition) fmt.Printf(" 图片URL: %s\n", item.ImgBigUrl) fmt.Printf(" 平均发货时间: %s\n", item.ShopAvgShippingTime) fmt.Printf(" 成功率: %s\n", item.ShopSuccessOrderRate) fmt.Printf(" 商品URL: %s\n", item.GoodsUrl) fmt.Printf(" 标题: %s\n", item.Title) fmt.Printf(" 图片数量: %d\n", item.GoodsImgCount) } // 如果需要转换为JSON jsonResult, err := json.MarshalIndent(result, "", " ") if err != nil { log.Printf("JSON序列化失败: %v", err) } else { fmt.Println("\n=== JSON格式输出 ===") fmt.Println(string(jsonResult)) } }