diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index 90501c67..8b84edd5 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -2,10 +2,8 @@ package mdb import ( "encoding/csv" - "encoding/json" "os" "path" - "sort" "strings" ice "github.com/shylinux/icebergs" @@ -19,255 +17,6 @@ func _domain_chain(m *ice.Message, chain string) string { return kit.Keys(m.Option(ice.MSG_DOMAIN), chain) } -func _hash_fields(m *ice.Message) []string { - return kit.Split(kit.Select("time,hash,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ","))) -} -func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) { - if m.Option(ice.MSG_DOMAIN) != "" { - m.Conf(prefix, kit.Keys(chain, kit.MDB_META, kit.MDB_SHORT), m.Conf(prefix, kit.Keys(kit.MDB_META, kit.MDB_SHORT))) - } - m.Log_INSERT(kit.MDB_KEY, path.Join(prefix, chain), arg[0], arg[1]) - h := m.Rich(prefix, chain, kit.Data(arg)) - m.Echo(h) -} -func _hash_delete(m *ice.Message, prefix, chain, field, value string) { - m.Richs(prefix, chain, value, func(key string, val map[string]interface{}) { - m.Log_DELETE(kit.MDB_KEY, path.Join(prefix, chain), field, value, kit.MDB_VALUE, kit.Format(val)) - m.Conf(prefix, kit.Keys(chain, kit.MDB_HASH, key), "") - }) -} -func _hash_select(m *ice.Message, prefix, chain, field, value string) { - if field == kit.MDB_HASH && value == RANDOM { - value = kit.MDB_RANDOMS - } - fields := _hash_fields(m) - cb := m.Optionv(kit.Keycb(SELECT)) - m.Richs(prefix, chain, value, func(key string, val map[string]interface{}) { - val = kit.GetMeta(val) - switch cb := cb.(type) { - case func(fields []string, value map[string]interface{}): - cb(fields, val) - default: - if m.Option(FIELDS) == DETAIL { - m.Push(DETAIL, val) - } else { - m.Push(key, val, fields) - } - } - }) - if m.Option(FIELDS) != DETAIL { - m.SortTimeR(kit.MDB_TIME) - } -} -func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) { - m.Richs(prefix, chain, value, func(key string, val map[string]interface{}) { - val = kit.GetMeta(val) - for i := 0; i < len(arg); i += 2 { - if arg[i] == field { - continue - } - kit.Value(val, arg[i], kit.Select("", arg, i+1)) - } - m.Log_MODIFY(kit.MDB_KEY, path.Join(prefix, chain), field, value, arg) - }) -} -func _hash_export(m *ice.Message, prefix, chain, file string) { - f, p, e := kit.Create(kit.Keys(file, JSON)) - m.Assert(e) - defer f.Close() - - en := json.NewEncoder(f) - en.SetIndent("", " ") - e = en.Encode(m.Confv(prefix, kit.Keys(chain, HASH))) - - m.Log_EXPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_FILE, p) - m.Echo(p) -} -func _hash_import(m *ice.Message, prefix, chain, file string) { - f, e := os.Open(kit.Keys(file, JSON)) - m.Assert(e) - defer f.Close() - - list := map[string]interface{}{} - de := json.NewDecoder(f) - de.Decode(&list) - - count := 0 - if m.Conf(prefix, kit.Keys(chain, kit.MDB_META, kit.MDB_SHORT)) == "" { - for k, data := range list { - m.Conf(prefix, kit.Keys(chain, kit.MDB_HASH, k), data) - count++ - } - } else { - for _, data := range list { - m.Rich(prefix, chain, data) - count++ - } - } - - m.Log_IMPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_COUNT, count) - m.Echo("%d", count) -} -func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) { - fields := _hash_fields(m) - m.Richs(prefix, chain, kit.MDB_FOREACH, func(key string, val map[string]interface{}) { - if val[kit.MDB_META] != nil { - val = val[kit.MDB_META].(map[string]interface{}) - } - switch cb := m.Optionv(kit.Keycb(PRUNES)).(type) { - case func(string, map[string]interface{}) bool: - if !cb(key, val) { - return - } - default: - for i := 0; i < len(arg)-1; i += 2 { - if val[arg[i]] != arg[i+1] { - return - } - } - } - m.Push(key, val, fields) - }) - m.Table(func(index int, value map[string]string, head []string) { - _hash_delete(m, prefix, chain, kit.MDB_HASH, value[kit.MDB_HASH]) - }) -} -func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) { - list := map[string]int{} - m.Richs(prefix, chain, kit.MDB_FOREACH, func(key string, val map[string]interface{}) { - val = kit.GetMeta(val) - if field == kit.MDB_HASH { - list[key]++ - } else { - list[kit.Format(val[field])]++ - } - }) - for k, i := range list { - m.Push(field, k) - m.Push(kit.MDB_COUNT, i) - } - m.Sort(kit.MDB_COUNT, "int_r") -} - -func _list_fields(m *ice.Message) []string { - return kit.Split(kit.Select("time,id,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ","))) -} -func _list_insert(m *ice.Message, prefix, chain string, arg ...string) { - m.Log_INSERT(kit.MDB_KEY, path.Join(prefix, chain), arg[0], arg[1]) - m.Echo("%d", m.Grow(prefix, chain, kit.Dict(arg))) -} -func _list_delete(m *ice.Message, prefix, chain, field, value string) { -} -func _list_select(m *ice.Message, prefix, chain, field, value string) { - if value == "" { - field = "" - } - fields := _list_fields(m) - cb := m.Optionv(kit.Keycb(SELECT)) - m.Grows(prefix, chain, kit.Select(m.Option(CACHE_FIELD), field), kit.Select(m.Option(CACHE_VALUE), value), func(index int, val map[string]interface{}) { - val = kit.GetMeta(val) - switch cb := cb.(type) { - case func(fields []string, value map[string]interface{}): - cb(fields, val) - default: - if m.Option(FIELDS) == DETAIL { - m.Push(DETAIL, val) - } else { - m.Push("", val, fields) - } - } - }) -} -func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) { - m.Grows(prefix, chain, field, value, func(index int, val map[string]interface{}) { - val = kit.GetMeta(val) - for i := 0; i < len(arg); i += 2 { - if arg[i] == field { - continue - } - kit.Value(val, arg[i], kit.Select("", arg, i+1)) - } - m.Log_MODIFY(kit.MDB_KEY, path.Join(prefix, chain), field, value, arg) - }) -} -func _list_export(m *ice.Message, prefix, chain, file string) { - f, p, e := kit.Create(kit.Keys(file, CSV)) - m.Assert(e) - defer f.Close() - - w := csv.NewWriter(f) - defer w.Flush() - - count := 0 - head := kit.Split(m.Option(FIELDS)) - m.Grows(prefix, chain, "", "", func(index int, val map[string]interface{}) { - if val = kit.GetMeta(val); index == 0 { - if len(head) == 0 { // 默认表头 - for k := range val { - head = append(head, k) - } - sort.Strings(head) - } - w.Write(head) // 输出表头 - } - - data := []string{} - for _, k := range head { - data = append(data, kit.Format(val[k])) - } - w.Write(data) // 输出数据 - count++ - }) - - m.Log_EXPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_FILE, p, kit.MDB_COUNT, count) - m.Echo(p) -} -func _list_import(m *ice.Message, prefix, chain, file string) { - f, e := os.Open(kit.Keys(file, CSV)) - m.Assert(e) - defer f.Close() - - r := csv.NewReader(f) - - count := 0 - head, _ := r.Read() - for { - line, e := r.Read() - if e != nil { - break - } - - data := kit.Dict() - for i, k := range head { - if k == kit.MDB_EXTRA { - kit.Value(data, k, kit.UnMarshal(line[i])) - } else { - kit.Value(data, k, line[i]) - } - } - - m.Grow(prefix, chain, data) - count++ - } - - m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, chain), kit.MDB_COUNT, count) - m.Echo("%d", count) -} -func _list_prunes(m *ice.Message, prefix, chain string, arg ...string) { -} -func _list_inputs(m *ice.Message, prefix, chain string, field, value string) { - list := map[string]int{} - m.Grows(prefix, chain, "", "", func(index int, val map[string]interface{}) { - val = kit.GetMeta(val) - list[kit.Format(val[field])]++ - }) - for k, i := range list { - m.Push(field, k) - m.Push(kit.MDB_COUNT, i) - } - m.SortIntR(kit.MDB_COUNT) -} - func _zone_fields(m *ice.Message) []string { return kit.Split(kit.Select("zone,id,time,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ","))) } @@ -409,8 +158,8 @@ const ( EXPORT = "export" IMPORT = "import" - PRUNES = "prunes" INPUTS = "inputs" + PRUNES = "prunes" REVERT = "revert" REPEAT = "repeat" UPLOAD = "upload" @@ -466,7 +215,7 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: map[string]* DELETE: {Name: "delete key sub type field value", Help: "删除", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[2] { case ZONE: - _hash_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4]) + _list_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4]) case HASH: _hash_delete(m, arg[0], _domain_chain(m, arg[1]), arg[3], arg[4]) case LIST: @@ -485,40 +234,32 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: map[string]* }}, SELECT: {Name: "select key sub type field value", Help: "查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch arg[2] { + case ZONE: + _zone_select(m, arg[0], _domain_chain(m, arg[1]), kit.Select("", arg, 3), kit.Select("", arg, 4)) case HASH: _hash_select(m, arg[0], _domain_chain(m, arg[1]), kit.Select("", arg, 3), kit.Select(kit.MDB_FOREACH, arg, 4)) case LIST: _list_select(m, arg[0], _domain_chain(m, arg[1]), kit.Select("", arg, 3), kit.Select("", arg, 4)) - case ZONE: - _zone_select(m, arg[0], _domain_chain(m, arg[1]), kit.Select("", arg, 3), kit.Select("", arg, 4)) } }}, EXPORT: {Name: "export key sub type file", Help: "导出", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch file := _file_name(m, arg...); arg[2] { + case ZONE: + _zone_export(m, arg[0], _domain_chain(m, arg[1]), file) case HASH: _hash_export(m, arg[0], _domain_chain(m, arg[1]), file) case LIST: _list_export(m, arg[0], _domain_chain(m, arg[1]), file) - case ZONE: - _zone_export(m, arg[0], _domain_chain(m, arg[1]), file) } }}, IMPORT: {Name: "import key sub type file", Help: "导入", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { switch file := _file_name(m, arg...); arg[2] { + case ZONE: + _zone_import(m, arg[0], _domain_chain(m, arg[1]), file) case HASH: _hash_import(m, arg[0], _domain_chain(m, arg[1]), file) case LIST: _list_import(m, arg[0], _domain_chain(m, arg[1]), file) - case ZONE: - _zone_import(m, arg[0], _domain_chain(m, arg[1]), file) - } - }}, - PRUNES: {Name: "prunes key sub type [field value]...", Help: "清理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - switch arg[2] { - case HASH: - _hash_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) - case LIST: - _list_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) } }}, INPUTS: {Name: "inputs key sub type field value", Help: "补全", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { @@ -531,6 +272,14 @@ var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: map[string]* _list_inputs(m, arg[0], _domain_chain(m, arg[1]), kit.Select("name", arg, 3), kit.Select("", arg, 4)) } }}, + PRUNES: {Name: "prunes key sub type [field value]...", Help: "清理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { + switch arg[2] { + case HASH: + _hash_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) + case LIST: + _list_prunes(m, arg[0], _domain_chain(m, arg[1]), arg[3:]...) + } + }}, }} func init() { diff --git a/core/mall/asset.go b/core/mall/asset.go index a9c60bb7..d5517cd1 100644 --- a/core/mall/asset.go +++ b/core/mall/asset.go @@ -31,25 +31,24 @@ func _sub_amount(m *ice.Message, arg []string) { func _asset_check(m *ice.Message, account string) { amount := 0 - m.OptionFields(m.Conf(ASSET, kit.META_FIELD)) - m.Option(kit.Keycb(mdb.SELECT), func(fields []string, value map[string]interface{}) { + m.Option(kit.Keycb(mdb.SELECT), func(key string, value map[string]interface{}) { amount += kit.Int(kit.Value(value, AMOUNT)) }) - m.Cmd(mdb.SELECT, ASSET, kit.KeyHash(account), mdb.LIST) + m.Cmd(mdb.SELECT, m.Prefix(ASSET), "", mdb.ZONE, account, ice.OptionFields(m.Conf(ASSET, kit.META_FIELD))) - m.Cmdy(mdb.MODIFY, ASSET, "", mdb.HASH, ACCOUNT, account, AMOUNT, amount) + m.Cmdy(mdb.MODIFY, m.Prefix(ASSET), "", mdb.HASH, ACCOUNT, account, AMOUNT, amount) } func _asset_create(m *ice.Message, account string) { - m.Cmdy(mdb.INSERT, ASSET, "", mdb.HASH, ACCOUNT, account) + m.Cmdy(mdb.INSERT, m.Prefix(ASSET), "", mdb.HASH, ACCOUNT, account) } func _asset_insert(m *ice.Message, account string, arg ...string) { _asset_create(m, account) - m.Cmdy(mdb.INSERT, ASSET, kit.KeyHash(account), mdb.LIST, arg) + m.Cmdy(mdb.INSERT, m.Prefix(ASSET), "", mdb.ZONE, account, arg) - m.Option(mdb.FIELDS, "time,account,amount,count") - amount := kit.Int(m.Cmd(mdb.SELECT, ASSET, "", mdb.HASH, ACCOUNT, account).Append(AMOUNT)) + m.OptionFields("time,account,amount,count") + amount := kit.Int(m.Cmd(mdb.SELECT, m.Prefix(ASSET), "", mdb.HASH, ACCOUNT, account).Append(AMOUNT)) amount += kit.Int(_sub_value(m, AMOUNT, arg...)) - m.Cmdy(mdb.MODIFY, ASSET, "", mdb.HASH, ACCOUNT, account, AMOUNT, amount) + m.Cmdy(mdb.MODIFY, m.Prefix(ASSET), "", mdb.HASH, ACCOUNT, account, AMOUNT, amount) } func _asset_inputs(m *ice.Message, field, value string) { switch strings.TrimPrefix(field, "extra.") { @@ -62,9 +61,9 @@ func _asset_inputs(m *ice.Message, field, value string) { case "arg": case ACCOUNT, FROM, TO: - m.Cmdy(mdb.INPUTS, ASSET, "", mdb.HASH, ACCOUNT, value) + m.Cmdy(mdb.INPUTS, m.Prefix(ASSET), "", mdb.HASH, ACCOUNT, value) default: - m.Cmdy(mdb.INPUTS, ASSET, kit.KeyHash(m.Option(ACCOUNT)), mdb.LIST, field, value) + m.Cmdy(mdb.INPUTS, m.Prefix(ASSET), "", mdb.ZONE, m.Option(ACCOUNT), field, value) } } @@ -119,22 +118,22 @@ func init() { }}, mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.MODIFY, ASSET, "", mdb.ZONE, m.Option(ACCOUNT), m.Option(kit.MDB_ID), arg) + m.Cmdy(mdb.MODIFY, m.Prefix(ASSET), "", mdb.ZONE, m.Option(ACCOUNT), m.Option(kit.MDB_ID), arg) }}, mdb.EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) { m.OptionFields(ACCOUNT, m.Conf(ASSET, kit.META_FIELD), kit.MDB_EXTRA) - m.Cmdy(mdb.EXPORT, ASSET, "", mdb.ZONE) + m.Cmdy(mdb.EXPORT, m.Prefix(ASSET), "", mdb.ZONE) }}, mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) { m.OptionFields(ACCOUNT) - m.Cmdy(mdb.IMPORT, ASSET, "", mdb.ZONE) + m.Cmdy(mdb.IMPORT, m.Prefix(ASSET), "", mdb.ZONE) }}, mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { _asset_inputs(m, kit.Select("", arg, 0), kit.Select("", arg, 1)) }}, mdb.PLUGIN: {Name: "plugin extra.pod extra.ctx extra.cmd extra.arg", Help: "插件", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.MODIFY, ASSET, "", mdb.ZONE, m.Option(ACCOUNT), m.Option(kit.MDB_ID), arg) + m.Cmdy(mdb.MODIFY, m.Prefix(ASSET), "", mdb.ZONE, m.Option(ACCOUNT), m.Option(kit.MDB_ID), arg) }}, ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(ctx.COMMAND, arg) @@ -145,7 +144,7 @@ func init() { }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { amount, count := 0, 0 m.Fields(len(arg), "time,account,amount,count", m.Conf(ASSET, kit.META_FIELD)) - if m.Cmdy(mdb.SELECT, ASSET, "", mdb.ZONE, arg); len(arg) == 0 { + if m.Cmdy(mdb.SELECT, m.Prefix(ASSET), "", mdb.ZONE, arg); len(arg) == 0 { m.PushAction(CHECK) m.SortIntR(AMOUNT) diff --git a/core/mall/salary.go b/core/mall/salary.go index b0ff0dba..970fec51 100644 --- a/core/mall/salary.go +++ b/core/mall/salary.go @@ -6,37 +6,44 @@ import ( kit "github.com/shylinux/toolkits" ) +const ( + MONTH = "month" + INCOME = "income" + TAX = "tax" +) const SALARY = "salary" func init() { Index.Merge(&ice.Context{ Configs: map[string]*ice.Config{ - SALARY: {Name: SALARY, Help: "工资", Value: kit.Data(kit.MDB_SHORT, "month")}, + SALARY: {Name: SALARY, Help: "工资", Value: kit.Data( + kit.MDB_SHORT, MONTH, kit.MDB_FIELD, "time,month,company,amount,income,tax", + )}, }, Commands: map[string]*ice.Command{ SALARY: {Name: "salary month auto create", Help: "工资", Action: map[string]*ice.Action{ mdb.CREATE: {Name: "create company month amount income tax 公积金 养老保险 医疗保险 生育保险 工伤保险 失业保险 企业公积金 企业养老保险 企业医疗保险 企业生育保险 企业工伤保险 企业失业保险", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.INSERT, SALARY, "", mdb.HASH, arg) + m.Cmdy(mdb.INSERT, m.Prefix(SALARY), "", mdb.HASH, arg) }}, mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.MODIFY, SALARY, "", mdb.HASH, "month", m.Option("month"), arg) + m.Cmdy(mdb.MODIFY, m.Prefix(SALARY), "", mdb.HASH, m.OptionSimple(MONTH), arg) }}, mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.MODIFY, SALARY, "", mdb.HASH, "month", m.Option("month")) + m.Cmdy(mdb.MODIFY, m.Prefix(SALARY), "", mdb.HASH, m.OptionSimple(MONTH)) }}, mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(mdb.INPUTS, SALARY, "", mdb.HASH, arg) + m.Cmdy(mdb.INPUTS, m.Prefix(SALARY), "", mdb.HASH, arg) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Fields(len(arg), "time,month,company,amount,income,tax") - m.Cmdy(mdb.SELECT, SALARY, "", mdb.HASH, "month", arg) + m.Fields(len(arg), m.Conf(SALARY, kit.META_FIELD)) + m.Cmdy(mdb.SELECT, m.Prefix(SALARY), "", mdb.HASH, MONTH, arg) amount, income, tax := 0, 0, 0 m.Table(func(index int, value map[string]string, head []string) { - amount += kit.Int(value["amount"]) - income += kit.Int(value["income"]) - tax += kit.Int(value["tax"]) + amount += kit.Int(value[AMOUNT]) + income += kit.Int(value[INCOME]) + tax += kit.Int(value[TAX]) }) - m.StatusTime("amount", amount, "income", income, "tax", tax) + m.StatusTime(AMOUNT, amount, INCOME, income, TAX, tax) }}, }, }) diff --git a/misc/lark/app.go b/misc/lark/app.go index 38722c3f..e30df6ef 100644 --- a/misc/lark/app.go +++ b/misc/lark/app.go @@ -35,7 +35,6 @@ func init() { m.Cmdy(mdb.INSERT, m.Prefix(APP), "", mdb.HASH, arg) }}, TOKEN: {Name: "token appid", Help: "令牌", Hand: func(m *ice.Message, arg ...string) { - m.Debug("what %v", m.Option(APPID)) msg := m.Cmd(APP, m.Option(APPID), ice.OptionFields(m.Conf(APP, kit.META_FIELD))) if now := time.Now().Unix(); msg.Append(TOKEN) == "" || now > kit.Int64(msg.Append(EXPIRE)) { sub := m.Cmd(web.SPIDE, LARK, web.SPIDE_POST, "/open-apis/auth/v3/tenant_access_token/internal/", diff --git a/type.go b/type.go index 7cc9acc0..ebc80f3f 100644 --- a/type.go +++ b/type.go @@ -241,15 +241,9 @@ func (c *Context) split(key string, cmd *Command, name string) []interface{} { button, list := false, []interface{}{} for _, v := range kit.Split(kit.Select("key", name), " ", " ")[1:] { - if key == "spend" { - fmt.Printf("what %v %v\n", key, v) - } switch v { case "text": list = append(list, kit.List(kit.MDB_INPUT, TEXTAREA, kit.MDB_NAME, "text")...) - if key == "spend" { - fmt.Printf("what %v %v\n", key, list) - } continue case "page": list = append(list, kit.List(kit.MDB_INPUT, TEXT, kit.MDB_NAME, "limit")...) @@ -383,8 +377,7 @@ type Message struct { I io.Reader } -func (m *Message) Time(args ...interface{}) string { - // [duration] [format [args...]] +func (m *Message) Time(args ...interface{}) string { // [duration] [format [args...]] t := m.time if len(args) > 0 { switch arg := args[0].(type) {