1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 16:58:06 +08:00

mac add ctx.select

This commit is contained in:
shaoying 2018-10-18 10:06:00 +08:00
parent 6d64c777c3
commit 5f328b5bc7
3 changed files with 211 additions and 105 deletions

View File

@ -133,7 +133,7 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
yac.Cmd("train", "stm", "goto", "goto", "exp", "opt{", "exp", "}", "exp") yac.Cmd("train", "stm", "goto", "goto", "exp", "opt{", "exp", "}", "exp")
yac.Cmd("train", "stm", "return", "return", "rep{", "exp", "}") yac.Cmd("train", "stm", "return", "return", "rep{", "exp", "}")
yac.Cmd("train", "word", "word", "mul{", "~", "!", "=", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}") yac.Cmd("train", "word", "word", "mul{", "~", "!", "=", "\\|", "exe", "str", "[a-zA-Z0-9_/\\-.:]+", "}")
yac.Cmd("train", "cmd", "cmd", "rep{", "word", "}") yac.Cmd("train", "cmd", "cmd", "rep{", "word", "}")
yac.Cmd("train", "exe", "exe", "$", "(", "cmd", ")") yac.Cmd("train", "exe", "exe", "$", "(", "cmd", ")")

View File

@ -1,6 +1,7 @@
package ctx package ctx
import ( import (
"encoding/csv"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -1349,6 +1350,12 @@ func (m *Message) Cmd(args ...interface{}) *Message {
if x, ok := s.Commands[key]; ok && x.Hand != nil { if x, ok := s.Commands[key]; ok && x.Hand != nil {
m.TryCatch(m, true, func(m *Message) { m.TryCatch(m, true, func(m *Message) {
m.Log("cmd", "%s:%s %v %v", s.Name, c.Name, m.Meta["detail"], m.Meta["option"]) m.Log("cmd", "%s:%s %v %v", s.Name, c.Name, m.Meta["detail"], m.Meta["option"])
rest := []string{}
for i := 0; i < len(arg); i++ {
if arg[i] == "|" {
arg, rest = arg[:i], arg[i+1:]
}
}
if args := []string{}; x.Form != nil { if args := []string{}; x.Form != nil {
for i := 0; i < len(arg); i++ { for i := 0; i < len(arg); i++ {
@ -1369,7 +1376,11 @@ func (m *Message) Cmd(args ...interface{}) *Message {
} }
x.Hand(m, s, key, arg...) x.Hand(m, s, key, arg...)
m.Hand = true
if m.Hand = true; len(rest) > 0 {
msg := m.Spawn().Copy(m, "option").Copy(m, "append").Cmd(rest)
m.Set("result").Set("append").Copy(msg, "result").Copy(msg, "append")
}
}) })
return m return m
} }
@ -2759,8 +2770,18 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
}}, }},
"command": &Command{ "command": &Command{
Name: "command [all|add cmd arg...|list [begin [end]]|test [begin [end]]|delete cmd]", Name: "command [all|add cmd arg...|list [begin [end]]|test [begin [end]]|delete cmd]",
Help: "查看或修改命令", Help: []string{
Form: map[string]int{"list_name": 1, "list_help": 1, "list_cache": 2, "list_index": 1, "condition": -1}, "查看或修改命令",
"list_export filename",
},
Form: map[string]int{
"list_name": 1,
"list_help": 1,
"list_cache": 2,
"list_index": 1,
"condition": -1,
"list_export": 1,
},
Hand: func(m *Message, c *Context, key string, arg ...string) { Hand: func(m *Message, c *Context, key string, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
keys := []string{} keys := []string{}
@ -2822,8 +2843,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
m.target.Commands[m.Cap("list_count")] = &Command{ m.target.Commands[m.Cap("list_count")] = &Command{
Name: strings.Join(arg[1:], " "), Name: strings.Join(arg[1:], " "),
Help: m.Confx("list_help"), Help: m.Confx("list_help"),
Hand: func(m *Message, c *Context, key string, args ...string) { Hand: func(cmd *Message, c *Context, key string, args ...string) {
m.Log("fcuK", "wat %v %v", args, list_index)
li := list_index li := list_index
if li == -1 { if li == -1 {
if len(args) > 0 { if len(args) > 0 {
@ -2835,7 +2855,7 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
list := []string{} list := []string{}
j := 0 j := 0
for i := 1; i < len(arg); i++ { for i := 1; i < len(arg); i++ {
if arg[i] == "_" && m.Assert(j < len(args)) { if arg[i] == "_" && cmd.Assert(j < len(args)) {
list = append(list, args[j]) list = append(list, args[j])
j++ j++
continue continue
@ -2844,17 +2864,22 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
} }
list = append(list, args[j:]...) list = append(list, args[j:]...)
msg := m.Spawn().Cmd(list) msg := cmd.Spawn().Cmd(list)
if len(msg.Meta["append"]) > 0 { if len(msg.Meta["append"]) > 0 {
for i, _ := range msg.Meta[msg.Meta["append"][0]] { for i, _ := range msg.Meta[msg.Meta["append"][0]] {
m.Add("append", "index", i) cmd.Add("append", "index", i)
} }
} }
if cache_name != "" && li > -1 { if cache_name != "" && li > -1 {
// m.Echo(m.Cap(cache_name, msg.Meta[cache_index][li])) // cmd.Echo(cmd.Cap(cache_name, msg.Meta[cache_index][li]))
m.Echo(m.Cap(cache_name, fmt.Sprint(msg.Confv(m.Confx("body_response"), cache_index)))) cmd.Echo(cmd.Cap(cache_name, fmt.Sprint(msg.Confv(cmd.Confx("body_response"), cache_index))))
} else { } else {
m.Copy(msg, "result").Copy(msg, "append") cmd.Copy(msg, "result").Copy(msg, "append")
if m.Has("list_export") {
export := cmd.Spawn()
export.Copy(cmd, "option").Copy(cmd, "append")
export.Cmd("export", m.Option("list_export"))
}
} }
}, },
} }
@ -3431,6 +3456,116 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
m.Echo(arg[0], values...) m.Echo(arg[0], values...)
m.Append("format", m.Result(0)) m.Append("format", m.Result(0))
}}, }},
"select": &Command{Name: "select key value", Form: map[string]int{"order": 2, "limit": 1, "offset": 1}, Help: "选取数据", Hand: func(m *Message, c *Context, key string, arg ...string) {
msg := m.Spawn()
offset := 0
limit := 10
if m.Has("limit") {
limit = m.Optioni("limit")
}
if m.Has("offset") {
offset = m.Optioni("offset")
}
n := 0
nrow := len(m.Meta[m.Meta["append"][0]])
for i := 0; i < nrow; i++ {
if len(arg) == 0 || strings.Contains(m.Meta[arg[0]][i], arg[1]) {
if n++; offset < n && n <= offset+limit {
for _, k := range m.Meta["append"] {
msg.Add("append", k, m.Meta[k][i])
}
}
}
}
if m.Set("append").Copy(msg, "append"); m.Has("order") {
m.Sort(m.Option("order"), m.Meta["order"][1])
}
m.Table()
}},
"import": &Command{Name: "import filename", Help: "导入数据", Hand: func(m *Message, c *Context, key string, arg ...string) {
f, e := os.Open(arg[0])
m.Assert(e)
defer f.Close()
switch {
case strings.HasSuffix(arg[0], ".json"):
var data interface{}
de := json.NewDecoder(f)
de.Decode(&data)
m.Optionv("data", data)
switch d := data.(type) {
case []interface{}:
for _, value := range d {
switch val := value.(type) {
case map[string]interface{}:
for k, v := range val {
m.Add("append", k, v)
}
}
}
}
case strings.HasSuffix(arg[0], ".csv"):
r := csv.NewReader(f)
l, e := r.Read()
m.Assert(e)
m.Meta["append"] = l
for {
l, e := r.Read()
if e != nil {
break
}
for i, v := range l {
m.Add("append", m.Meta["append"][i], v)
}
}
}
m.Table()
}},
"export": &Command{Name: "export filename", Help: "导出数据", Hand: func(m *Message, c *Context, key string, arg ...string) {
f, e := os.Create(arg[0])
m.Assert(e)
defer f.Close()
switch {
case strings.HasSuffix(arg[0], ".json"):
data := []interface{}{}
nrow := len(m.Meta[m.Meta["append"][0]])
for i := 0; i < nrow; i++ {
line := map[string]interface{}{}
for _, k := range m.Meta["append"] {
line[k] = m.Meta[k][i]
}
data = append(data, line)
}
en := json.NewEncoder(f)
en.SetIndent("", " ")
en.Encode(data)
case strings.HasSuffix(arg[0], ".csv"):
w := csv.NewWriter(f)
line := []string{}
for _, v := range m.Meta["append"] {
line = append(line, v)
}
w.Write(line)
nrow := len(m.Meta[m.Meta["append"][0]])
for i := 0; i < nrow; i++ {
line := []string{}
for _, k := range m.Meta["append"] {
line = append(line, m.Meta[k][i])
}
w.Write(line)
}
w.Flush()
}
}},
}, },
} }

View File

@ -3,19 +3,14 @@ package mdb
import ( import (
"contexts/ctx" "contexts/ctx"
"database/sql" "database/sql"
"encoding/json"
"fmt" "fmt"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"os"
"strconv"
"strings" "strings"
) )
type MDB struct { type MDB struct {
*sql.DB *sql.DB
db []string
table []string
*ctx.Context *ctx.Context
} }
@ -29,13 +24,15 @@ func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
"driver": &ctx.Cache{Name: "数据库驱动(mysql)", Value: m.Confx("driver", arg, 5), Help: "数据库驱动"}, "driver": &ctx.Cache{Name: "数据库驱动(mysql)", Value: m.Confx("driver", arg, 5), Help: "数据库驱动"},
} }
c.Configs = map[string]*ctx.Config{ c.Configs = map[string]*ctx.Config{
"table": &ctx.Config{Name: "关系表", Value: "", Help: "关系表"}, "dbs": &ctx.Config{Name: "dbs", Value: []string{}, Help: "关系表"},
"tables": &ctx.Config{Name: "dbs", Value: []string{}, Help: "关系表"},
"table": &ctx.Config{Name: "关系表", Value: "0", Help: "关系表"},
"field": &ctx.Config{Name: "字段名", Value: "", Help: "字段名"}, "field": &ctx.Config{Name: "字段名", Value: "", Help: "字段名"},
"where": &ctx.Config{Name: "条件", Value: "", Help: "条件"}, "where": &ctx.Config{Name: "条件", Value: "", Help: "条件"},
"group": &ctx.Config{Name: "聚合", Value: "", Help: "聚合"}, "group": &ctx.Config{Name: "聚合", Value: "", Help: "聚合"},
"order": &ctx.Config{Name: "排序", Value: "", Help: "排序"}, "order": &ctx.Config{Name: "排序", Value: "", Help: "排序"},
"limit": &ctx.Config{Name: "分页", Value: "", Help: "分页"}, "limit": &ctx.Config{Name: "分页", Value: "10", Help: "分页"},
"offset": &ctx.Config{Name: "偏移", Value: "", Help: "偏移"}, "offset": &ctx.Config{Name: "偏移", Value: "0", Help: "偏移"},
"parse": &ctx.Config{Name: "解析", Value: "", Help: "解析"}, "parse": &ctx.Config{Name: "解析", Value: "", Help: "解析"},
} }
@ -43,11 +40,9 @@ func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
s.Context = c s.Context = c
return s return s
} }
func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server {
return mdb return mdb
} }
func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool {
db, e := sql.Open(m.Cap("driver"), fmt.Sprintf("%s:%s@%s(%s)/%s", db, e := sql.Open(m.Cap("driver"), fmt.Sprintf("%s:%s@%s(%s)/%s",
m.Cap("username"), m.Cap("password"), m.Cap("protocol"), m.Cap("address"), m.Cap("database"))) m.Cap("username"), m.Cap("password"), m.Cap("protocol"), m.Cap("address"), m.Cap("database")))
@ -56,7 +51,6 @@ func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool {
m.Log("info", "mdb open %s", m.Cap("database")) m.Log("info", "mdb open %s", m.Cap("database"))
return false return false
} }
func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool {
switch mdb.Context { switch mdb.Context {
case m.Target(): case m.Target():
@ -65,7 +59,6 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool {
return false return false
} }
var Pulse *ctx.Message
var Index = &ctx.Context{Name: "mdb", Help: "数据中心", var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
Caches: map[string]*ctx.Cache{ Caches: map[string]*ctx.Cache{
"nsource": &ctx.Cache{Name: "数据源数量", Value: "0", Help: "已打开数据库的数量"}, "nsource": &ctx.Cache{Name: "数据源数量", Value: "0", Help: "已打开数据库的数量"},
@ -82,11 +75,19 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
"csv_row_sep": &ctx.Config{Name: "记录分隔符", Value: "\n", Help: "记录分隔符"}, "csv_row_sep": &ctx.Config{Name: "记录分隔符", Value: "\n", Help: "记录分隔符"},
}, },
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
"open": &ctx.Command{ "open": &ctx.Command{Name: "open [database [username [password [address [protocol [driver]]]]]]",
Name: "open [database [username [password [address [protocol [driver]]]]]]",
Help: "open打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 服务地址, protocol: 服务协议, driver: 数据库类型", Help: "open打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 服务地址, protocol: 服务协议, driver: 数据库类型",
Form: map[string]int{"dbname": 1, "dbhelp": 1},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Start(fmt.Sprintf("db%d", m.Capi("nsource", 1)), "数据源", arg...) dbname := fmt.Sprintf("db%d", m.Capi("nsource", 1))
dbhelp := "数据源"
if m.Has("dbname") {
dbname = m.Option("dbname")
}
if m.Has("dbhelp") {
dbname = m.Option("dbhelp")
}
m.Start(dbname, dbhelp, arg...)
}}, }},
"exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 操作参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 操作参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil { if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil {
@ -131,6 +132,8 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
for i, k := range cols { for i, k := range cols {
switch b := vals[i].(type) { switch b := vals[i].(type) {
case nil:
m.Add("append", k, "")
case []byte: case []byte:
m.Add("append", k, string(b)) m.Add("append", k, string(b))
case int64: case int64:
@ -152,67 +155,49 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil { if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) && mdb.DB != nil {
if len(arg) == 0 { if len(arg) == 0 {
msg := m.Spawn().Cmd("query", "show databases") msg := m.Spawn().Cmd("query", "show databases")
mdb.db = []string{} dbs := []string{}
for i, v := range msg.Meta[msg.Meta["append"][0]] { for i, v := range msg.Meta[msg.Meta["append"][0]] {
mdb.db = append(mdb.db, v) dbs = append(dbs, v)
m.Echo("%d: %s\n", i, v) m.Echo("%d: %s\n", i, v)
} }
m.Target().Configs["dbs"].Value = dbs
return return
} }
db := arg[0] db := m.Confv("dbs", arg[0]).(string)
if i, e := strconv.Atoi(arg[0]); e == nil && i < len(mdb.db) {
db = mdb.db[i]
}
m.Assert(m.Spawn().Cmd("exec", fmt.Sprintf("use %s", db))) m.Assert(m.Spawn().Cmd("exec", fmt.Sprintf("use %s", db)))
m.Echo(m.Cap("database", db)) m.Echo(m.Cap("database", db))
} }
}}, }},
"table": &ctx.Command{Name: "table [which [field]]", Help: "查看关系表信息which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { "tab": &ctx.Command{Name: "tab[which [field]]", Help: "查看关系表信息which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { if _, ok := m.Target().Server.(*MDB); m.Assert(ok) {
if len(arg) == 0 { if len(arg) == 0 {
msg := m.Spawn().Cmd("query", "show tables") msg := m.Spawn().Cmd("query", "show tables")
mdb.table = []string{} tables := []string{}
for i, v := range msg.Meta[msg.Meta["append"][0]] { for i, v := range msg.Meta[msg.Meta["append"][0]] {
mdb.table = append(mdb.table, v) tables = append(tables, v)
m.Echo("%d: %s\n", i, v) m.Echo("%d: %s\n", i, v)
} }
m.Target().Configs["tables"].Value = tables
return return
} }
table := arg[0] table := m.Confv("tables", arg[0]).(string)
if i, e := strconv.Atoi(arg[0]); e == nil && i < len(mdb.table) {
table = mdb.table[i]
}
msg := m.Spawn().Cmd("query", fmt.Sprintf("desc %s", table)) msg := m.Spawn().Cmd("query", fmt.Sprintf("desc %s", table))
if len(arg) == 1 { m.Copy(msg, "append")
for _, v := range msg.Meta[msg.Meta["append"][0]] { m.Table()
m.Echo("%s\n", v)
}
return
}
for i, v := range msg.Meta[msg.Meta["append"][0]] {
if v == arg[1] {
for _, k := range msg.Meta["append"] {
m.Echo("%s: %s\n", k, msg.Meta[k][i])
}
}
}
} }
}}, }},
"show": &ctx.Command{Name: "show table fields...", "show": &ctx.Command{Name: "show table fields...",
Help: "查询数据库, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段", Help: "查询数据库, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段",
Form: map[string]int{"where": 1, "group": 1, "order": 1, "limit": 1, "offset": 1, "other": -1, Form: map[string]int{"where": 1, "group": 1, "order": 1, "limit": 1, "offset": 1, "other": -1,
"extras": 1, "extra_field": 1, "extra_format": 1, "trans_field": 1, "trans_map": 2, "extra_field": 1, "extra_chains": 1, "extra_format": 1, "trans_field": 1, "trans_map": 2},
"save": 1, "export": 2,
},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { if _, ok := m.Target().Server.(*MDB); m.Assert(ok) {
table := m.Confx("table", arg, 0) table := m.Confx("table", arg, 0)
if i, e := strconv.Atoi(table); e == nil && i < len(mdb.table) { if v := m.Confv("tables", table); v != nil {
table = mdb.table[i] table = v.(string)
} }
fields := []string{"*"} fields := []string{"*"}
@ -243,26 +228,39 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
msg := m.Spawn().Cmd("query", fmt.Sprintf("select %s from %s %s %s %s %s %s", field, table, where, group, order, limit, offset), other) msg := m.Spawn().Cmd("query", fmt.Sprintf("select %s from %s %s %s %s %s %s", field, table, where, group, order, limit, offset), other)
m.Copy(msg, "append") m.Copy(msg, "append")
if m.Optioni("query", msg.Code()); !m.Options("save") {
m.Color(31, table).Echo(" %s %s %s %s %s %v\n", where, group, order, limit, offset, m.Meta["other"]) m.Target().Configs["template_value"] = &ctx.Config{}
if m.Has("extra_field") && len(m.Meta[m.Option("extra_field")]) > 0 {
format := "%v"
if m.Has("extra_format") {
format = m.Option("extra_format")
}
for i := 0; i < len(m.Meta[m.Option("extra_field")]); i++ {
json.Unmarshal([]byte(m.Meta[m.Option("extra_field")][i]), &m.Target().Configs["template_value"].Value)
switch v := m.Confv("template_value", m.Option("extra_chains")).(type) {
default:
m.Meta[m.Option("extra_field")][i] = fmt.Sprintf(format, v)
}
}
} }
if m.Has("trans_field") {
trans := map[string]string{}
for i := 0; i < len(m.Meta["trans_map"]); i += 2 {
trans[m.Meta["trans_map"][i]] = m.Meta["trans_map"][i+1]
}
for i := 0; i < len(m.Meta[m.Option("trans_field")]); i++ {
if t, ok := trans[m.Meta[m.Option("trans_field")][i]]; ok {
m.Meta[m.Option("trans_field")][i] = t
}
}
}
m.Color(31, table).Echo(" %s %s %s %s %s %v\n", where, group, order, limit, offset, m.Meta["other"])
m.Table(func(maps map[string]string, lists []string, line int) bool { m.Table(func(maps map[string]string, lists []string, line int) bool {
for i, v := range lists { for i, v := range lists {
if m.Options("save") { if line == -1 {
key := m.Meta["append"][i]
value := maps[key]
if key == m.Option("trans_field") {
for i := 0; i < len(m.Meta["trans_map"])-1; i += 2 {
if value == m.Meta["trans_map"][i] {
value = m.Meta["trans_map"][i+1]
break
}
}
}
m.Echo(value)
} else if line == -1 {
m.Color(32, v) m.Color(32, v)
} else { } else {
m.Echo(v) m.Echo(v)
@ -274,33 +272,6 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
m.Echo(m.Conf("csv_row_sep")) m.Echo(m.Conf("csv_row_sep"))
return true return true
}) })
if m.Options("export") {
f, e := os.Create(m.Option("export"))
m.Assert(e)
defer f.Close()
m.Table(func(maps map[string]string, lists []string, line int) bool {
if line > -1 {
args := []interface{}{}
for i := 0; i < len(lists); i++ {
args = append(args, maps[m.Meta["append"][i]])
}
f.WriteString(fmt.Sprintf(m.Meta["export"][1], args...))
}
return true
})
}
if m.Options("save") {
f, e := os.Create(m.Option("save"))
m.Assert(e)
defer f.Close()
for _, v := range m.Meta["result"] {
f.WriteString(v)
}
}
} }
}}, }},
}, },