使用blob作为分区键时gocql反序列化失败问题求助
解决gocql查询Cassandra Blob类型分区键时的反序列化问题
我来帮你搞定这个问题——你碰到的can not unmarshal blob into *[20]uint8错误,核心原因是查询参数的类型不匹配,以及gocql对Blob类型和Go数组类型的映射规则。咱们一步步拆解解决:
问题根源
你用fmt.Sprintf把SHA1哈希([20]uint8类型)转成了十六进制字符串(比如0xd03dde1610d6df87a90619412ceda6e5320528dd),然后把这个字符串作为查询参数传给Cassandra。但Cassandra的Blob类型存储的是二进制数据,gocql需要直接接收二进制类型的参数,而不是格式化后的字符串。另外,当你用*[20]uint8接收返回值时,需要确保查询返回的二进制数据能直接映射到这个数组类型。
解决方案
1. 直接传递二进制参数,而非十六进制字符串
SHA1的Sum方法返回的是[20]uint8,你可以直接把它转换成[]byte(切片)作为查询参数,不需要转成十六进制字符串。gocql会自动把[]byte映射到Cassandra的Blob类型。
2. 正确接收返回值
你可以用[20]uint8变量直接接收返回的Blob数据,或者先接收成[]byte再复制到数组里(两种方式都可行)。
修正后的代码示例
下面是调整后的完整查询代码,包括可能的插入逻辑(确保数据正确存储):
package main import ( "fmt" "log" "crypto/sha1" "github.com/gocql/gocql" ) func main() { cluster := gocql.NewCluster("10.0.0.1") cluster.Keyspace = "ks" cluster.Consistency = gocql.Quorum cluster.ProtoVersion = 4 cluster.Authenticator = gocql.PasswordAuthenticator{ Username: "cassandra", Password: "cassandra", } session, err := cluster.CreateSession() if err != nil { log.Fatalf("Failed to create session: %v", err) } defer session.Close() text := "text before hashed" data := []byte(text) // SHA1哈希得到[20]uint8 hashValue := sha1.Sum(data) // 先确保数据已经正确插入(如果之前没插入的话) insertQuery := `INSERT INTO sample (hash_value, column1) VALUES (?, ?)` err = session.Query(insertQuery, hashValue[:], 123).Exec() if err != nil { log.Fatalf("Insert failed: %v", err) } fmt.Println("Data inserted successfully") // 执行查询:直接传递[]byte类型的参数 var returnedHash [20]uint8 var column1 int query := `SELECT hash_value, column1 FROM sample WHERE hash_value = ? LIMIT 1` err = session.Query(query, hashValue[:]).Consistency(gocql.One).Scan(&returnedHash, &column1) if err != nil { log.Fatalf("Query failed: %v", err) } // 验证结果 fmt.Printf("Returned hash: %v\n", returnedHash) fmt.Printf("Returned column1: %d\n", column1) // 对比原始哈希和返回的哈希 if returnedHash == hashValue { fmt.Println("Hash matches!") } }
关键注意点
- 插入数据时:同样要传递
hashValue[:]([]byte类型),而不是十六进制字符串,确保Cassandra存储的是正确的Blob二进制数据。 - 查询参数:绝对不要用格式化后的十六进制字符串(比如
0x...),直接用二进制切片即可。 - 类型匹配:gocql可以自动在Cassandra Blob和Go的
[]byte、[N]uint8之间转换,只要参数和接收变量的类型对应上就不会报错。
内容的提问来源于stack exchange,提问作者simotunes
相关产品推荐
相关产品推荐

