错误未知类型转到 [英] Error unknown type Go
问题描述
load2redis
这是代码。它有点长,只是在这里忍着。
包主
导入(
字节
数据库/ sql
标志
//github.com/garyburd/redigo/redis
_github.com/go- sql-driver / mysql
//\"gopkg.in/redis.v4
github.com/chasex/redis-go-cluster
log
运行时
//字符串
同步
时间
)
var client * redis.Cluster
类型任务接口{
Execute()
}
类型池结构{
mu sync.Mutex
size int
任务chan任务
kill chan struct {}
wg sync.WaitGroup
}
func NewPool(size int)* Pool {
pool:=& Pool {
tasks:make(chan Task,128),
kill:make(chan struct {}),
}
pool.Resize大小)
返回池
}
func(p * Pool)worker(){
推迟p.wg.Done()
for {
选择{
case task,ok:=< -p.tasks:
if!ok {
return
}
task.Execute()
case< -p.kill:
return
}
}
}
func(p * Pool)Resize(n int){
p.mu.Lock()
推迟p.mu.Unlock()
为p.size< n {
p.size ++
p.wg.Add(1)
go p.worker()
}
for p.size> n {
p.size--
p.kill< - struct {} {}
}
}
func(p * Pool) Close(){
close(p.tasks)
}
func(p * Pool)Wait(){
p.wg.Wait()
$ func(p * Pool)Exec(任务任务){
p.tasks< - 任务
}
类型RedisTask struct {
索引int
命令字符串
键字符串
字符串
MapData map [字符串]字符串
}
func( e)RedisTask)Execute(){
log.Println(执行:,e.Key,,,e.Index)
如果e.Command ==SET{
_,err:= redis.String(client.Do(SET,e.Key,e.Value))
checkErr(err,set error:)
} else如果e.Command ==SADD{
_,err:= redis.Strings(client.Do(SADD,e.Key,e.Value))
checkErr(err,sadd错误:)
} else if e.Command ==HMSET{
_,err:= redis.StringMap(client.Do(HMSET,e.Key,e.MapData))
checkEr r(err,hmset error:)
}
// TODO:clean data
}
func main(){
runtime.GOMAXPROCS (runtime.NumCPU())
startTime:= time.Now()。UnixNano()/ int64(time.Millisecond)
host:= flag.String(s,localhost:3306 ,mysql server host and port,eg localhost:3306)
username:= flag.String(u,test,username to login mysql)
password:= flag.String (p,test,password for mysql)
database:= flag.String(d,test,要执行查询的数据库)
query:= flag.String(q,select 1;,your query sql)
ds:= flag.String(ds,key,redis structure)
PK: = flag.String(pk,Rkey,redis在mysql查询结果字段中的键值)
// redisHost:= flag.String(rs,localhost: 6379,redis主机和端口,例如localhost:6379)
// redisPassword:= flag.String(rp,test,redis password)
poolSize := flag.Int(size,10000,redis pool s ize)
flag.Parse()
var buf bytes.Buffer = bytes.Buffer {}
buf.WriteString(* username)
buf.WriteString( :)
buf.WriteString(* password)
buf.WriteString(@ tcp()
buf.WriteString(* host)
buf.WriteString() /)
buf.WriteString(* database)
db,err:= sql.Open(mysql,buf.String())
checkErr(err,连接到mysql错误!)
defer db.Close()
poolWorker:= NewPool(* poolSize)
//执行查询
行,err:= db.Query(* query)
checkErr(err,执行sql错误!)
// pool = newPool(* redisHost,* redisPassword,* poolSize)
// client = redis.NewClient(& redis.Options {
// Addr:* redisHost,
//密码:* redisPassword,//无密码设置
// DB:0,//使用默认的DB
//})
客户端,_ = redis.NewCluster(& redis.Options {
Sta rtNodes:[] string {10.xxx:6000,10.xxx:6001,10.xxx:6002},
ConnTimeout:50 * time.Millisecond,
ReadTimeout:50 * time.Millisecond,
WriteTimeout:50 * time.Millisecond,
KeepAlive:16,
AliveTime:60 * time.Second,
})
// checkErr (err,client error:)
// pong,err:= client.Ping()。Result()
// checkErr(err,redis client error:)
//log.Println(pong)
列,err:= rows.Columns()
checkErr(err,获取列错误!)
length:= len(列)
values:= make([] sql.RawBytes,length)
scanArgs:= make([] interface {},len(values) )
for i:=范围值{
scanArgs [i] =& values [i]
}
count:= 0
for rows .Next(){
count + = 1
err = rows.Scan(scanArgs ...)
checkErr(err,scan error)
var VA lue string
var key string
var任务RedisTask
if * ds ==key{
key = getStringData(values [0])
value = getStringData(values [1])$ b $ b if value!={
task = RedisTask {
索引:count,
命令:SET,
Key:key,
Value:value,
}
}
} else if * ds ==set{
key = getStringData(values [b]
value = getStringData(values [1])$ b $ b if value!={
task = RedisTask {
Index:count,
Command: SADD,
Key:key,
Value:value,
}
}
} else if * ds ==hash{
key = getStringData(values [0])
添加(键)
$ bm:= make(map [string]字符串)
for i,col:=范围值{/ / args:= redis.Args {}。
如果col!= nil&&列[i]!= * PK {
value = getStringData(col)
m [columns [i]] = value
}
}
task = RedisTask {
索引:count,
命令:HMSET,
键:键,
MapData:m,
}
}
poolWorker.Exec (任务)
}
if err = rows.Err(); err!= nil {
panic(err.Error())//正确的错误处理,而不是应用程序中的恐慌
}
poolWorker.Close()
poolWorker.Wait()
EndTime:= time.Now()。UnixNano()/ int64(time.Millisecond)
log.Println(===== ===================================执行时间:,EndTime-startTimems,总数: ,count)
}
func getStringData(data sql.RawBytes)string {
if data == nil {
return
}
value:string(data)
return clearBad(value)
}
func clearBad(str string)string {
// str = strings.Trim (str,`)
// str = strings.Trim(str,½€)
// str = strings.Trim(str, - )
// str = strings.Trim(str,。)
// str = strings.Trim(str,)
// str = strings.Trim(str,;)
// str = strings.Trim(str,,)
// str = strings.Trim(str,:)
// str = strings.Trim(str,; )
// str = strings.Trim(str,')
// str = strings.Trim(str,!)
return str
}
func checkErr(err error,msg string){
if err!= nil {
log.Fatalln(msg,err)
}
}
$ c $
<$ p $选择CONCAT('student:',c.sid)Rkey,c.sname SNAME,c .saddress SADDRESS,c.sage SAGE FROM STUDENT c WHERE c.sid> 0;-ds hash -size 1200
2017/07/21 10:29:09 rak.go:93:执行:student:2,2
2017/07/21 10:29:09 rak.go:93:正在执行:学生:1,
2017/07/21 10:29:09 rak.go:93:正在执行:学生:3,3
2017/07/21 10 :29:09 rak.go:268:hmset错误:Do:unknown type map [string] string
$
有人可以向我解释我在这里做错了什么吗?我会非常感激。
正如所指出的, Do
不适用于地图,这是您可以修复它的一种方式。
<$ p $如果e.Command ==HMSET{
//建立一个字符串片来保存键值对
args:= make([] string, 0,len(e.MapData)* 2)
for k,v:= range e.MapData {
args = append(args,k,v)
}
_ ,err:= redis.StringMap(client.Do(HMSET,e.Key,args ...))
checkErr(err,hmset error:)
}
Do方法映射到预计Redis命令集和参数的方式相同。例如。
127.0.0.1:6379> HMSET myKey foo bar baz boff
OK
127.0.0.1:6379> HGETALL myKey
1)foo
2)bar
3)baz
4)boff
127.0.0.1:6379>
在您的代码中使用redis客户端的相同映射集操作将是
client.Do(HMSET,myKey,foo,bar,baz,boff)
当地图的键和值的参数是动态的时,最简单的方法是
client.Do(HMSET,myKey,[] string {foo,bar,baz,boff} ...)
这正是上面第一个代码块的功能。
i'm really new to Go, su just bear with me here. I'm trying to write a code for loading mysql data to redis cluster using following :redis-go-cluster, load2redis
This is the code. Its a little bit long, just bear with me here.
package main
import (
"bytes"
"database/sql"
"flag"
// "github.com/garyburd/redigo/redis"
_ "github.com/go-sql-driver/mysql"
//"gopkg.in/redis.v4"
"github.com/chasex/redis-go-cluster"
"log"
"runtime"
// "strings"
"sync"
"time"
)
var client *redis.Cluster
type Task interface {
Execute()
}
type Pool struct {
mu sync.Mutex
size int
tasks chan Task
kill chan struct{}
wg sync.WaitGroup
}
func NewPool(size int) *Pool {
pool := &Pool{
tasks: make(chan Task, 128),
kill: make(chan struct{}),
}
pool.Resize(size)
return pool
}
func (p *Pool) worker() {
defer p.wg.Done()
for {
select {
case task, ok := <-p.tasks:
if !ok {
return
}
task.Execute()
case <-p.kill:
return
}
}
}
func (p *Pool) Resize(n int) {
p.mu.Lock()
defer p.mu.Unlock()
for p.size < n {
p.size++
p.wg.Add(1)
go p.worker()
}
for p.size > n {
p.size--
p.kill <- struct{}{}
}
}
func (p *Pool) Close() {
close(p.tasks)
}
func (p *Pool) Wait() {
p.wg.Wait()
}
func (p *Pool) Exec(task Task) {
p.tasks <- task
}
type RedisTask struct {
Index int
Command string
Key string
Value string
MapData map[string]string
}
func (e RedisTask) Execute() {
log.Println("executing:", e.Key, ",", e.Index)
if e.Command == "SET" {
_,err := redis.String(client.Do("SET", e.Key, e.Value))
checkErr(err, "set error:")
} else if e.Command == "SADD" {
_,err := redis.Strings(client.Do("SADD", e.Key, e.Value))
checkErr(err, "sadd error:")
} else if e.Command == "HMSET" {
_,err := redis.StringMap(client.Do("HMSET", e.Key, e.MapData))
checkErr(err, "hmset error:")
}
// TODO: clean data
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
startTime := time.Now().UnixNano() / int64(time.Millisecond)
host := flag.String("s", "localhost:3306", "mysql server host and port ,eg localhost:3306")
username := flag.String("u", "test", "username to login mysql")
password := flag.String("p", "test", "password for mysql")
database := flag.String("d", "test", "database you want to execute query")
query := flag.String("q", "select 1;", "your query sql")
ds := flag.String("ds", "key", "redis structure")
PK := flag.String("pk", "Rkey", "the redis Key in the fields of mysql query result")
//redisHost := flag.String("rs", "localhost:6379", "redis host and port ,eg localhost:6379")
//redisPassword := flag.String("rp", "test", "redis password")
poolSize := flag.Int("size", 10000, "redis pool size")
flag.Parse()
var buf bytes.Buffer = bytes.Buffer{}
buf.WriteString(*username)
buf.WriteString(":")
buf.WriteString(*password)
buf.WriteString("@tcp(")
buf.WriteString(*host)
buf.WriteString(")/")
buf.WriteString(*database)
db, err := sql.Open("mysql", buf.String())
checkErr(err, "connect to mysql error !")
defer db.Close()
poolWorker := NewPool(*poolSize)
// Execute the query
rows, err := db.Query(*query)
checkErr(err, "execute sql error!")
// pool = newPool(*redisHost, *redisPassword, *poolSize)
//client = redis.NewClient(&redis.Options{
// Addr: *redisHost,
// Password: *redisPassword, // no password set
// DB: 0, // use default DB
//})
client,_ = redis.NewCluster(&redis.Options{
StartNodes: []string{"10.x.x.x:6000", "10.x.x.x:6001", "10.x.x.x:6002"},
ConnTimeout: 50 * time.Millisecond,
ReadTimeout: 50 * time.Millisecond,
WriteTimeout: 50 * time.Millisecond,
KeepAlive: 16,
AliveTime: 60 * time.Second,
})
//checkErr(err, "client error:")
//pong, err := client.Ping().Result()
//checkErr(err, "redis client error:")
//log.Println(pong)
columns, err := rows.Columns()
checkErr(err, "get columns error!")
length := len(columns)
values := make([]sql.RawBytes, length)
scanArgs := make([]interface{}, len(values))
for i := range values {
scanArgs[i] = &values[i]
}
count := 0
for rows.Next() {
count += 1
err = rows.Scan(scanArgs...)
checkErr(err, "scan error")
var value string
var key string
var task RedisTask
if *ds == "key" {
key = getStringData(values[0])
value = getStringData(values[1])
if value != "" {
task = RedisTask{
Index: count,
Command: "SET",
Key: key,
Value: value,
}
}
} else if *ds == "set" {
key = getStringData(values[0])
value = getStringData(values[1])
if value != "" {
task = RedisTask{
Index: count,
Command: "SADD",
Key: key,
Value: value,
}
}
} else if *ds == "hash" {
key = getStringData(values[0])
// args := redis.Args{}.Add(key)
m := make(map[string]string)
for i, col := range values {
if col != nil && columns[i] != *PK {
value = getStringData(col)
m[columns[i]] = value
}
}
task = RedisTask{
Index: count,
Command: "HMSET",
Key: key,
MapData: m,
}
}
poolWorker.Exec(task)
}
if err = rows.Err(); err != nil {
panic(err.Error()) // proper error handling instead of panic in your app
}
poolWorker.Close()
poolWorker.Wait()
EndTime := time.Now().UnixNano() / int64(time.Millisecond)
log.Println("======================================== executing time:", EndTime-startTime, " ms, total:", count)
}
func getStringData(data sql.RawBytes) string {
if data == nil {
return ""
}
value := string(data)
return clearBad(value)
}
func clearBad(str string) string {
// str = strings.Trim(str, "`")
// str = strings.Trim(str, "ï½€")
// str = strings.Trim(str, "-")
// str = strings.Trim(str, ".")
// str = strings.Trim(str, " ")
// str = strings.Trim(str, ";")
// str = strings.Trim(str, ",")
// str = strings.Trim(str, ":")
// str = strings.Trim(str, ";")
// str = strings.Trim(str, "'")
// str = strings.Trim(str, "!")
return str
}
func checkErr(err error, msg string) {
if err != nil {
log.Fatalln(msg, err)
}
}
When i'm executing it, i'm getting following exception:
./rak -u user -p user -s 10.X.X.X:8080 -d test -q "SELECT CONCAT( 'student:', c.sid ) Rkey, c.sname SNAME, c.saddress SADDRESS, c.sage SAGE FROM STUDENT c WHERE c.sid > 0;" -ds hash -size 1200
2017/07/21 10:29:09 rak.go:93: executing: student:2 , 2
2017/07/21 10:29:09 rak.go:93: executing: student:1 , 1
2017/07/21 10:29:09 rak.go:93: executing: student:3 , 3
2017/07/21 10:29:09 rak.go:268: hmset error: Do: unknown type map[string]string
$
Can somebody explain to me what i'm doing wrong here? I'd be very grateful.
As pointed out, Do
does not work with maps. This is one way you could fix it.
} else if e.Command == "HMSET" {
// Build up a string slice to hold the key value pairs
args := make([]string, 0, len(e.MapData) * 2)
for k, v := range e.MapData {
args = append(args, k, v)
}
_,err := redis.StringMap(client.Do("HMSET", e.Key, args...))
checkErr(err, "hmset error:")
}
The Do method maps to the Redis command set and arguments are expected in the same way. For example.
127.0.0.1:6379> HMSET myKey foo bar baz boff
OK
127.0.0.1:6379> HGETALL myKey
1) "foo"
2) "bar"
3) "baz"
4) "boff"
127.0.0.1:6379>
The same map-set operation using the redis client in your code would be
client.Do("HMSET", "myKey", "foo", "bar", "baz", "boff")
When the arguments for keys and values of the map are dynamic, the most straight forward way is
client.Do("HMSET", "myKey", []string{"foo", "bar", "baz", "boff"}...)
which is exactly what the first code block above does.
这篇关于错误未知类型转到的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!