335 lines
9.1 KiB
Go
335 lines
9.1 KiB
Go
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))
|
||
}
|
||
}
|