1
0
forked from x/ContextOS

opt context

This commit is contained in:
shylinux 2019-06-30 13:37:11 +08:00
parent 4842117198
commit abdf1711bb
23 changed files with 2764 additions and 2870 deletions

View File

@ -1,5 +1,5 @@
BENCH=src/examples/app/bench.go BENCH=src/extend/bench.go
upgrade=usr/upgrade/ upgrade=usr/upgrade/
install: install:

View File

@ -46,9 +46,9 @@ hup() {
} }
main() { main() {
trap HUP hup trap HUP hup
log "\nstarting..."
while true; do while true; do
date date && ${ctx_bin} "$@" && break
${ctx_bin} "$@" && break
log "\nrestarting..." && sleep 1 log "\nrestarting..." && sleep 1
done done
} }

View File

@ -36,13 +36,10 @@ type AAA struct {
func Auto(m *ctx.Message, arg ...string) { func Auto(m *ctx.Message, arg ...string) {
msg := m.Spawn().Add("option", "auto_cmd", "").Cmd("auth", arg) msg := m.Spawn().Add("option", "auto_cmd", "").Cmd("auth", arg)
msg.Table(func(maps map[string]string, list []string, line int) bool { msg.Table(func(line int, maps map[string]string) {
if line >= 0 { m.Add("append", "value", maps["key"])
m.Add("append", "value", maps["key"]) m.Add("append", "name", fmt.Sprintf("%s: %s", maps["type"], maps["meta"]))
m.Add("append", "name", fmt.Sprintf("%s: %s", maps["type"], maps["meta"])) m.Add("append", "help", fmt.Sprintf("%s", maps["create_time"]))
m.Add("append", "help", fmt.Sprintf("%s", maps["create_time"]))
}
return true
}) })
} }

View File

@ -152,7 +152,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}, },
}, Help: "运行环境"}, }, Help: "运行环境"},
"compile": &ctx.Config{Name: "compile", Value: map[string]interface{}{ "compile": &ctx.Config{Name: "compile", Value: map[string]interface{}{
"bench": "src/examples/app/bench.go", "bench": "src/extend/bench.go",
"tmp": "var/tmp/go", "tmp": "var/tmp/go",
"env": []interface{}{"GOPATH", "PATH"}, "env": []interface{}{"GOPATH", "PATH"},
}, Help: "运行环境"}, }, Help: "运行环境"},
@ -444,7 +444,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
m.Echo(h) m.Echo(h)
// 执行命令 // 执行命令
m.GoFunc(m, func(m *ctx.Message) { m.Gos(m, func(m *ctx.Message) {
if e := cmd.Start(); e != nil { if e := cmd.Start(); e != nil {
m.Echo("error: ").Echo("%s\n", e) m.Echo("error: ").Echo("%s\n", e)
} else if e := cmd.Wait(); e != nil { } else if e := cmd.Wait(); e != nil {
@ -457,7 +457,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
// 管道命令 // 管道命令
wait := make(chan bool, 1) wait := make(chan bool, 1)
m.GoFunc(m, func(m *ctx.Message) { m.Gos(m, func(m *ctx.Message) {
defer func() { wait <- true }() defer func() { wait <- true }()
out := bytes.NewBuffer(make([]byte, 0, 1024)) out := bytes.NewBuffer(make([]byte, 0, 1024))
@ -745,17 +745,30 @@ var version = struct {
"missyou": &ctx.Command{Name: "missyou", Help: "服务升级", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { "missyou": &ctx.Command{Name: "missyou", Help: "服务升级", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 { if len(arg) == 0 {
m.Option("dir_root", "") m.Option("dir_root", "")
m.Cmdy("nfs.dir", m.Conf("missyou", "path")) m.Cmd("nfs.dir", m.Conf("missyou", "path")).Table(func() {
})
return return
} }
p := path.Join(m.Conf("missyou", "path"), m.Time("20060102-")+arg[0]) if !strings.Contains(arg[0], "-") {
m.Cmd("nfs.copy", path.Join(p, "etc/local.shy"), "usr/missyou/job.shy") arg[0] = m.Time("20060102-") + arg[0]
}
if m.Confs("ssh.node", arg[0]) {
m.Echo(arg[0])
return
}
p := path.Join(m.Conf("missyou", "path"), arg[0])
if s, e := os.Stat(p); e == nil && s.IsDir() {
m.Cmdy("cli.system", "node.sh", "create", p, "daemon", "cmd_daemon", "true")
return e
}
m.Cmdy("nfs.copy", path.Join(p, "etc/local.shy"), "usr/missyou/job.shy")
m.Confm("missyou", "local", func(index string, local string) { m.Confm("missyou", "local", func(index string, local string) {
m.Cmd("nfs.git", "clone", local, path.Join(p, "usr/local", index)) m.Cmd("nfs.git", "clone", local, path.Join(p, "usr/local", index))
}) })
m.Cmdy("cli.system", "node.sh", "create", p, "daemon", "cmd_daemon", "true")
return return
}}, }},
"quit": &ctx.Command{Name: "quit code", Help: "停止服务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { "quit": &ctx.Command{Name: "quit code", Help: "停止服务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -779,7 +792,7 @@ var version = struct {
m.Append("code", code) m.Append("code", code)
m.Echo(", wait 1s\n").Table() m.Echo(", wait 1s\n").Table()
m.GoFunc(m, func(m *ctx.Message) { m.Gos(m, func(m *ctx.Message) {
defer func() { defer func() {
os.Exit(kit.Int(code)) os.Exit(kit.Int(code))
}() }()
@ -798,25 +811,25 @@ var version = struct {
} }
begin := time.Now() begin := time.Now()
f, e := os.Open(args[0]) f, e := os.Open(args[0])
defer f.Close() defer f.Close()
bio := bufio.NewScanner(f) bio := bufio.NewScanner(f)
output := map[string]*os.File{} output := map[string]*os.File{}
nreq := 0 nreq := 0
for bio.Scan() { for bio.Scan() {
word := strings.Split(bio.Text(), " ") word := strings.Split(bio.Text(), " ")
if len(word) != 2 { if len(word) != 2 {
continue continue
} }
uri := word[0][prefix0:len(word[0])-1] uri := word[0][prefix0 : len(word[0])-1]
arg := word[1][prefix1:len(word[1])-1] arg := word[1][prefix1 : len(word[1])-1]
if output[uri] == nil { if output[uri] == nil {
output[uri], e = os.Create(path.Join("tmp", strings.Replace(uri, "/", "_", -1)+".txt")) output[uri], e = os.Create(path.Join("tmp", strings.Replace(uri, "/", "_", -1)+".txt"))
defer output[uri].Close() defer output[uri].Close()
} }
nreq++ nreq++
br := bytes.NewReader([]byte(arg)) br := bytes.NewReader([]byte(arg))
res, e := http.Post(args[1]+uri, "application/json", br) res, e := http.Post(args[1]+uri, "application/json", br)
fmt.Fprintf(output[uri], uri) fmt.Fprintf(output[uri], uri)
fmt.Fprintf(output[uri], " ") fmt.Fprintf(output[uri], " ")

View File

@ -4,5 +4,5 @@ var version = struct {
host string host string
self int self int
}{ }{
"2019-06-28 19:50:49", "ZYB-20190522USI", 24, "2019-06-30 12:52:58", "com", 26,
} }

View File

@ -554,21 +554,19 @@ var CGI = template.FuncMap{
if len(cli.Meta["append"]) > 0 { if len(cli.Meta["append"]) > 0 {
result = append(result, "<table>") result = append(result, "<table>")
result = append(result, "<caption>", cmd, "</caption>") result = append(result, "<caption>", cmd, "</caption>")
cli.Table(func(maps map[string]string, list []string, line int) bool { cli.Table(func(line int, maps map[string]string) {
if line == -1 { if line == 0 {
result = append(result, "<tr>") result = append(result, "<tr>")
for _, v := range list { for _, v := range cli.Meta["append"] {
result = append(result, "<th>", v, "</th>") result = append(result, "<th>", v, "</th>")
} }
result = append(result, "</tr>") result = append(result, "</tr>")
return true
} }
result = append(result, "<tr>") result = append(result, "<tr>")
for _, v := range list { for _, k := range cli.Meta["append"] {
result = append(result, "<td>", v, "</td>") result = append(result, "<td>", maps[k], "</td>")
} }
result = append(result, "</tr>") result = append(result, "</tr>")
return true
}) })
result = append(result, "</table>") result = append(result, "</table>")
} else { } else {

391
src/contexts/ctx/core.go Normal file
View File

@ -0,0 +1,391 @@
package ctx
import (
"errors"
"io"
"strings"
"time"
"toolkit"
)
func (c *Context) Register(s *Context, x Server, args ...interface{}) {
force := false
if len(args) > 0 {
switch arg := args[0].(type) {
case bool:
force = arg
}
}
if c.contexts == nil {
c.contexts = make(map[string]*Context)
}
if x, ok := c.contexts[s.Name]; ok && !force {
panic(errors.New(c.Name + "上下文中已存在模块:" + x.Name))
}
c.contexts[s.Name] = s
s.context = c
s.Server = x
}
func (c *Context) Plugin(args []string) string {
Index.Register(c, nil)
m := &Message{code: 0, time: time.Now(), source: c, target: c, Meta: map[string][]string{}}
if len(args) == 0 {
m.Echo("%s: %s\n", c.Name, c.Help)
for k, v := range c.Commands {
m.Echo("%s: %s %v\n", k, v.Name, v.Help)
}
} else if cs, ok := c.Commands[args[0]]; ok {
h := cs.Hand
if e := h(m, c, args[0], args[1:]...); e != nil {
m.Echo("error: ").Echo("%v\n", e)
}
} else {
m.Echo("error: ").Echo("not found: %v\n", args[0])
}
return strings.Join(m.Meta["result"], "")
}
func (c *Context) Spawn(m *Message, name string, help string) *Context {
s := &Context{Name: name, Help: help, root: c.root, context: c, message: m,
Caches: map[string]*Cache{},
Configs: map[string]*Config{},
Commands: map[string]*Command{},
}
if m.target = s; c.Server != nil {
c.Register(s, c.Server.Spawn(m, s, m.Meta["detail"]...))
} else {
c.Register(s, nil)
}
return s
}
func (c *Context) Begin(m *Message, arg ...string) *Context {
if len(arg) > 0 {
m.Set("detail", arg)
}
module := c.Name
if c.context != nil && c.context.Caches != nil && c.context.Caches["module"] != nil {
module = c.context.Caches["module"].Value + "." + c.Name
}
c.Caches["module"] = &Cache{Name: "module", Value: module, Help: "模块域名"}
c.Caches["status"] = &Cache{Name: "status(begin/start/close)", Value: "begin", Help: "模块状态, begin: 初始完成, start: 正在运行, close: 运行结束"}
c.Caches["stream"] = &Cache{Name: "stream", Value: "", Help: "模块数据"}
c.message = m
c.requests = append(c.requests, m)
m.source.sessions = append(m.source.sessions, m)
c.exit = make(chan bool, 3)
/*
m.Log("begin", "%d context %v %v", m.Capi("ncontext", 1), m.Meta["detail"], m.Meta["option"])
for k, x := range c.Configs {
if x.Hand != nil {
m.Log("begin", "%s config %v", k, m.Conf(k, x.Value))
}
}
*/
if c.Server != nil {
c.Server.Begin(m, m.Meta["detail"]...)
}
return c
}
func (c *Context) Start(m *Message, arg ...string) bool {
sync := false
if len(arg) > 0 && arg[0] == "sync" {
sync, arg = true, arg[1:]
}
if len(arg) > 0 {
m.Set("detail", arg)
}
c.requests = append(c.requests, m)
m.source.sessions = append(m.source.sessions, m)
if m.Hand = true; m.Cap("status") == "start" {
return true
}
m.Gos(m, func(m *Message) {
m.Log(m.Cap("status", "start"), "%d server %v %v", m.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"])
c.message = m
if c.exit <- false; c.Server == nil || c.Server.Start(m, m.Meta["detail"]...) {
c.Close(m, m.Meta["detail"]...)
c.exit <- true
}
}, func(m *Message) {
c.Close(m, m.Meta["detail"]...)
c.exit <- true
})
if sync {
for !<-c.exit {
}
return true
}
return <-c.exit
}
func (c *Context) Close(m *Message, arg ...string) bool {
if len(c.requests) == 0 {
return true
}
if m.target == c {
for i := len(c.requests) - 1; i >= 0; i-- {
if msg := c.requests[i]; msg.code == m.code {
if c.Server == nil || c.Server.Close(m, arg...) {
m.Log("close", "request %d/%d", i, len(c.requests)-1)
msg.Free()
for j := i; j < len(c.requests)-1; j++ {
c.requests[j] = c.requests[j+1]
}
c.requests = c.requests[:len(c.requests)-1]
}
}
}
}
if len(c.requests) > 0 {
return false
}
if m.Cap("status") == "start" {
m.Log(m.Cap("status", "close"), "%d server %v", m.root.Capi("nserver", -1), arg)
for _, msg := range c.sessions {
if msg.Cap("status") != "close" {
msg.target.Close(msg, arg...)
}
}
}
if c.context != nil {
m.Log("close", "%d context %v", m.root.Capi("ncontext", -1), arg)
delete(c.context.contexts, c.Name)
c.exit <- true
}
return true
}
func (m *Message) Assert(e interface{}, msg ...string) bool {
switch v := e.(type) {
case nil:
return true
case *Message:
if v.Result(0) != "error: " {
return true
}
e = errors.New(strings.Join(v.Meta["result"], ""))
default:
if kit.Right(v) {
return true
}
}
switch e.(type) {
case error:
default:
e = errors.New(kit.Format(msg))
}
kit.Log("error", "%v", e)
panic(e)
}
func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
defer func() {
switch e := recover(); e {
case io.EOF:
case nil:
default:
m.Log("bench", "chain: %s", msg.Format("chain"))
m.Log("bench", "catch: %s", e)
m.Log("bench", "stack: %s", msg.Format("stack"))
if m.Log("error", "catch: %s", e); len(hand) > 1 {
m.TryCatch(msg, safe, hand[1:]...)
} else if !safe {
m.Assert(e)
}
}
}()
if len(hand) > 0 {
hand[0](msg)
}
return m
}
func (m *Message) Gos(msg *Message, hand ...func(msg *Message)) *Message {
go func() {
msg.Option("routine", m.Capi("ngo", 1))
m.TryCatch(msg, true, hand...)
}()
return m
}
func (m *Message) Spawn(arg ...interface{}) *Message {
temp := false
c := m.target
if len(arg) > 0 {
switch v := arg[0].(type) {
case *Context:
c = v
case *Message:
c = v.target
case string:
temp = kit.Right(v)
}
}
msg := &Message{
time: time.Now(),
code: m.Capi("nmessage", 1),
source: m.target,
target: c,
message: m,
root: m.root,
}
if temp {
return msg
}
m.messages = append(m.messages, msg)
return msg
}
func (m *Message) Sess(key string, arg ...interface{}) *Message {
if key == "" {
return m.Spawn()
}
spawn := true
if len(arg) > 0 {
switch v := arg[0].(type) {
case bool:
spawn, arg = v, arg[1:]
}
}
if len(arg) > 0 {
if m.Sessions == nil {
m.Sessions = make(map[string]*Message)
}
switch value := arg[0].(type) {
case *Message:
m.Sessions[key] = value
return m.Sessions[key]
case *Context:
m.Sessions[key] = m.Spawn(value)
return m.Sessions[key]
case string:
root := len(arg) < 3 || kit.Right(arg[2])
method := "find"
if len(arg) > 1 {
method = kit.Format(arg[1])
}
switch method {
case "find":
m.Sessions[key] = m.Find(value, root)
case "search":
m.Sessions[key] = m.Search(value, root)[0]
}
return m.Sessions[key]
case nil:
delete(m.Sessions, key)
return nil
}
}
for msg := m; msg != nil; msg = msg.message {
if x, ok := msg.Sessions[key]; ok {
if spawn {
x = m.Spawn(x.target)
x.callback = func(sub *Message) *Message { return sub }
}
return x
}
}
return nil
}
func (m *Message) Call(cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
if m == nil {
return m
}
if m.callback = cb; len(arg) > 0 || len(m.Meta["detail"]) > 0 {
m.Log("call", m.Format("detail", "option"))
m.Cmd(arg...)
}
return m
}
func (m *Message) Back(ms ...*Message) *Message {
if m.callback == nil {
return m
}
if len(ms) == 0 {
ms = append(ms, m.Spawn(m.source).Copy(m, "append").Copy(m, "result"))
}
ns := []*Message{}
for _, msg := range ms {
if msg.Hand {
m.Log("back", msg.Format("ship", "result", "append"))
} else {
m.Log("back", msg.Format("ship", "detail", "option"))
}
if sub := m.callback(msg); sub != nil && m.message != nil && m.message != m {
ns = append(ns, sub)
}
}
if len(ns) > 0 {
m.message.Back(ns...)
}
return m
}
func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg ...interface{}) *Message {
if !sync {
return m.Call(cb, arg...)
}
wait := make(chan *Message, 10)
// m.Gos(m, func(m *Message) {
m.Call(func(sub *Message) *Message {
msg := cb(sub)
m.Log("sync", m.Format("done", "result", "append"))
wait <- m
return msg
}, arg...)
// })
m.Log("sync", m.Format("wait", "result", "append"))
select {
case <-time.After(kit.Duration(m.Conf("call_timeout"))):
m.Log("sync", m.Format("timeout", "result", "append"))
case <-wait:
}
return m
}
func (m *Message) Free(cbs ...func(msg *Message) (done bool)) *Message {
if len(cbs) == 0 {
for i := len(m.freeback) - 1; i >= 0; i-- {
m.Log("free", "%d/%d", i, len(m.freeback)-1)
if !m.freeback[i](m) {
break
}
m.freeback = m.freeback[:i]
}
return m
}
m.freeback = append(m.freeback, cbs...)
return m
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,12 @@
package ctx package ctx
import ( import (
"fmt"
"math/rand"
"strconv"
"strings"
"time" "time"
"toolkit"
) )
type Cache struct { type Cache struct {
@ -48,6 +53,14 @@ type Server interface {
Start(m *Message, arg ...string) bool Start(m *Message, arg ...string) bool
Close(m *Message, arg ...string) bool Close(m *Message, arg ...string) bool
} }
func (c *Context) Context() *Context {
return c.context
}
func (c *Context) Message() *Message {
return c.message
}
type Message struct { type Message struct {
time time.Time time time.Time
code int code int
@ -55,19 +68,17 @@ type Message struct {
source *Context source *Context
target *Context target *Context
Hand bool
Meta map[string][]string Meta map[string][]string
Data map[string]interface{} Data map[string]interface{}
callback func(msg *Message) (sub *Message) callback func(msg *Message) (sub *Message)
freedoms []func(msg *Message) (done bool) freeback []func(msg *Message) (done bool)
Sessions map[string]*Message Sessions map[string]*Message
messages []*Message messages []*Message
message *Message message *Message
root *Message root *Message
Remote chan bool
Hand bool
} }
type LOGGER interface { type LOGGER interface {
Log(*Message, string, string, ...interface{}) Log(*Message, string, string, ...interface{})
@ -76,3 +87,789 @@ type DEBUG interface {
Wait(*Message, ...interface{}) interface{} Wait(*Message, ...interface{}) interface{}
Goon(interface{}, ...interface{}) Goon(interface{}, ...interface{})
} }
func (m *Message) Time(arg ...interface{}) string {
t := m.time
if len(arg) > 0 {
if d, e := time.ParseDuration(arg[0].(string)); e == nil {
arg = arg[1:]
t.Add(d)
}
}
str := m.Conf("time_format")
if len(arg) > 1 {
str = fmt.Sprintf(arg[0].(string), arg[1:]...)
} else if len(arg) > 0 {
str = fmt.Sprintf("%v", arg[0])
}
if str == "stamp" {
return kit.Format(t.Unix())
}
return t.Format(str)
}
func (m *Message) Code() int {
return m.code
}
func (m *Message) Source() *Context {
return m.source
}
func (m *Message) Target() *Context {
return m.target
}
func (m *Message) Message() *Message {
return m.message
}
func (m *Message) Detail(arg ...interface{}) string {
noset, index := true, 0
if len(arg) > 0 {
switch v := arg[0].(type) {
case int:
noset, index, arg = false, v, arg[1:]
}
}
if noset && len(arg) > 0 {
index = -2
}
return m.Insert("detail", index, arg...)
}
func (m *Message) Detaili(arg ...interface{}) int {
return kit.Int(m.Detail(arg...))
}
func (m *Message) Details(arg ...interface{}) bool {
return kit.Right(m.Detail(arg...))
}
func (m *Message) Option(key string, arg ...interface{}) string {
if len(arg) > 0 {
m.Insert(key, 0, arg...)
if _, ok := m.Meta[key]; ok {
m.Add("option", key)
}
}
for msg := m; msg != nil; msg = msg.message {
if !msg.Has(key) {
continue
}
for _, k := range msg.Meta["option"] {
if k == key {
return msg.Get(key)
}
}
}
return ""
}
func (m *Message) Optioni(key string, arg ...interface{}) int {
return kit.Int(m.Option(key, arg...))
}
func (m *Message) Options(key string, arg ...interface{}) bool {
return kit.Right(m.Option(key, arg...))
}
func (m *Message) Optionv(key string, arg ...interface{}) interface{} {
if len(arg) > 0 {
switch arg[0].(type) {
case nil:
// case []string:
// m.Option(key, v...)
// case string:
// m.Option(key, v)
default:
m.Put("option", key, arg[0])
}
}
for msg := m; msg != nil; msg = msg.message {
if msg.Meta == nil || !msg.Has(key) {
continue
}
for _, k := range msg.Meta["option"] {
if k == key {
if v, ok := msg.Data[key]; ok {
return v
}
return msg.Meta[key]
}
}
}
return nil
}
func (m *Message) Optionx(key string, arg ...string) interface{} {
value := m.Conf(key)
if value == "" {
value = m.Option(key)
}
if len(arg) > 0 {
value = fmt.Sprintf(arg[0], value)
}
return value
}
func (m *Message) Append(key string, arg ...interface{}) string {
if len(arg) > 0 {
m.Insert(key, 0, arg...)
if _, ok := m.Meta[key]; ok {
m.Add("append", key)
}
}
ms := []*Message{m}
for i := 0; i < len(ms); i++ {
ms = append(ms, ms[i].messages...)
if !ms[i].Has(key) {
continue
}
for _, k := range ms[i].Meta["append"] {
if k == key {
return ms[i].Get(key)
}
}
}
return ""
}
func (m *Message) Appendi(key string, arg ...interface{}) int64 {
i, _ := strconv.ParseInt(m.Append(key, arg...), 10, 64)
return i
}
func (m *Message) Appends(key string, arg ...interface{}) bool {
return kit.Right(m.Append(key, arg...))
}
func (m *Message) Appendv(key string, arg ...interface{}) interface{} {
if len(arg) > 0 {
m.Put("append", key, arg[0])
}
ms := []*Message{m}
for i := 0; i < len(ms); i++ {
ms = append(ms, ms[i].messages...)
if !ms[i].Has(key) {
continue
}
for _, k := range ms[i].Meta["append"] {
if k == key {
if v, ok := ms[i].Data[key]; ok {
return v
}
return ms[i].Meta[key]
}
}
}
return nil
}
func (m *Message) Result(arg ...interface{}) string {
noset, index := true, 0
if len(arg) > 0 {
switch v := arg[0].(type) {
case int:
noset, index, arg = false, v, arg[1:]
}
}
if noset && len(arg) > 0 {
index = -2
}
return m.Insert("result", index, arg...)
}
func (m *Message) Resulti(arg ...interface{}) int {
return kit.Int(m.Result(arg...))
}
func (m *Message) Results(arg ...interface{}) bool {
return kit.Right(m.Result(arg...))
}
func (m *Message) Table(cbs ...interface{}) *Message {
if len(m.Meta["append"]) == 0 {
return m
}
// 遍历函数
if len(cbs) > 0 {
nrow := len(m.Meta[m.Meta["append"][0]])
for i := 0; i < nrow; i++ {
line := map[string]string{}
for _, k := range m.Meta["append"] {
line[k] = m.Meta[k][i]
}
switch cb := cbs[0].(type) {
case func(map[string]string):
cb(line)
case func(map[string]string) bool:
if !cb(line) {
return m
}
case func(int, map[string]string):
cb(i, line)
}
}
return m
}
//计算列宽
space := m.Confx("table_space")
depth, width := 0, map[string]int{}
for _, k := range m.Meta["append"] {
if len(m.Meta[k]) > depth {
depth = len(m.Meta[k])
}
width[k] = kit.Width(k, len(space))
for _, v := range m.Meta[k] {
if kit.Width(v, len(space)) > width[k] {
width[k] = kit.Width(v, len(space))
}
}
}
// 回调函数
var cb func(maps map[string]string, list []string, line int) (goon bool)
if len(cbs) > 0 {
cb = cbs[0].(func(maps map[string]string, list []string, line int) (goon bool))
} else {
row := m.Confx("table_row_sep")
col := m.Confx("table_col_sep")
compact := kit.Right(m.Confx("table_compact"))
cb = func(maps map[string]string, lists []string, line int) bool {
for i, v := range lists {
if k := m.Meta["append"][i]; compact {
v = maps[k]
}
if m.Echo(v); i < len(lists)-1 {
m.Echo(col)
}
}
m.Echo(row)
return true
}
}
// 输出表头
row := map[string]string{}
wor := []string{}
for _, k := range m.Meta["append"] {
row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-kit.Width(k, len(space))))
}
if !cb(row, wor, -1) {
return m
}
// 输出数据
for i := 0; i < depth; i++ {
row := map[string]string{}
wor := []string{}
for _, k := range m.Meta["append"] {
data := ""
if i < len(m.Meta[k]) {
data = m.Meta[k][i]
}
row[k], wor = data, append(wor, data+strings.Repeat(space, width[k]-kit.Width(data, len(space))))
}
m.Log("fuck", "waht %v", row)
if !cb(row, wor, i) {
break
}
}
return m
}
func (m *Message) Sort(key string, arg ...string) *Message {
cmp := "str"
if len(arg) > 0 {
cmp = arg[0]
}
number := map[int]int{}
table := []map[string]string{}
m.Table(func(index int, line map[string]string) {
table = append(table, line)
switch cmp {
case "int":
number[index] = kit.Int(line[key])
case "int_r":
number[index] = -kit.Int(line[key])
case "time":
number[index] = kit.Time(line[key])
case "time_r":
number[index] = -kit.Time(line[key])
}
})
for i := 0; i < len(table)-1; i++ {
for j := i + 1; j < len(table); j++ {
result := false
switch cmp {
case "str":
if table[i][key] > table[j][key] {
result = true
}
case "str_r":
if table[i][key] < table[j][key] {
result = true
}
default:
if number[i] > number[j] {
result = true
}
}
if result {
table[i], table[j] = table[j], table[i]
number[i], number[j] = number[j], number[i]
}
}
}
for _, k := range m.Meta["append"] {
delete(m.Meta, k)
}
for _, v := range table {
for _, k := range m.Meta["append"] {
m.Add("append", k, v[k])
}
}
return m
}
func (m *Message) Copy(msg *Message, arg ...string) *Message {
if msg == nil || m == msg {
return m
}
for i := 0; i < len(arg); i++ {
meta := arg[i]
switch meta {
case "target":
m.target = msg.target
case "callback":
m.callback = msg.callback
case "detail", "result":
if len(msg.Meta[meta]) > 0 {
m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
}
case "option", "append":
if msg.Meta == nil {
msg.Meta = map[string][]string{}
}
if msg.Meta[meta] == nil {
break
}
if i == len(arg)-1 {
arg = append(arg, msg.Meta[meta]...)
}
for i++; i < len(arg); i++ {
if v, ok := msg.Data[arg[i]]; ok {
m.Put(meta, arg[i], v)
} else if v, ok := msg.Meta[arg[i]]; ok {
m.Set(meta, arg[i], v) // TODO fuck Add
}
}
default:
if msg.Hand {
meta = "append"
} else {
meta = "option"
}
if v, ok := msg.Data[arg[i]]; ok {
m.Put(meta, arg[i], v)
}
if v, ok := msg.Meta[arg[i]]; ok {
m.Add(meta, arg[i], v)
}
}
}
return m
}
func (m *Message) Echo(str string, arg ...interface{}) *Message {
if len(arg) > 0 {
return m.Add("result", fmt.Sprintf(str, arg...))
}
return m.Add("result", str)
}
func (m *Message) Cmdp(t time.Duration, head []string, prefix []string, suffix [][]string) *Message {
if head != nil && len(head) > 0 {
m.Show(strings.Join(head, " "), "...\n")
}
for i, v := range suffix {
m.Show(fmt.Sprintf("%v/%v %v...\n", i+1, len(suffix), v))
m.CopyFuck(m.Cmd(prefix, v), "append")
time.Sleep(t)
}
m.Show("\n")
m.Table()
return m
}
func (m *Message) Cmdm(args ...interface{}) *Message {
m.Log("info", "current: %v", m.Magic("session", "current"))
arg := []string{}
if pod := kit.Format(m.Magic("session", "current.pod")); pod != "" {
arg = append(arg, "context", "ssh", "remote", pod)
}
if ctx := kit.Format(m.Magic("session", "current.ctx")); ctx != "" {
arg = append(arg, "context", ctx)
}
arg = append(arg, kit.Trans(args...)...)
m.Spawn().Cmd(arg).CopyTo(m)
return m
}
func (m *Message) Cmdy(args ...interface{}) *Message {
m.Cmd(args...).CopyTo(m)
return m
}
func (m *Message) Cmdx(args ...interface{}) string {
msg := m.Cmd(args...)
if msg.Result(0) == "error: " {
return msg.Result(1)
}
return msg.Result(0)
}
func (m *Message) Cmds(args ...interface{}) bool {
return m.Cmd(args...).Results(0)
}
func (m *Message) Cmd(args ...interface{}) *Message {
if m == nil {
return m
}
if len(args) > 0 {
m.Set("detail", kit.Trans(args...))
}
key, arg := m.Meta["detail"][0], m.Meta["detail"][1:]
msg := m
if strings.Contains(key, ":") {
ps := strings.Split(key, ":")
msg, key, arg = msg.Sess("ssh"), "_route", append([]string{"sync", ps[0], ps[1]}, arg...)
defer func() { m.Copy(msg, "append").Copy(msg, "result") }()
m.Hand = true
} else if strings.Contains(key, ".") {
arg := strings.Split(key, ".")
msg, key = msg.Sess(arg[0]), arg[1]
msg.Option("remote_code", "")
}
if msg == nil {
return msg
}
msg = msg.Match(key, true, func(msg *Message, s *Context, c *Context, key string) bool {
msg.Hand = false
if x, ok := c.Commands[key]; ok && x.Hand != nil {
msg.TryCatch(msg, true, func(msg *Message) {
msg.Log("cmd", "%s %s %v %v", c.Name, key, arg, msg.Meta["option"])
for _, form := range []map[string]int{map[string]int{"page.limit": 1, "page.offset": 1}, x.Form} {
if args := []string{}; form != nil {
for i := 0; i < len(arg); i++ {
if n, ok := form[arg[i]]; ok {
if n < 0 {
n += len(arg) - i
}
for j := i + 1; j <= i+n && j < len(arg); j++ {
if _, ok := form[arg[j]]; ok {
n = j - i - 1
}
}
if i+1+n > len(arg) {
msg.Add("option", arg[i], arg[i+1:])
} else {
msg.Add("option", arg[i], arg[i+1:i+1+n])
}
i += n
} else {
args = append(args, arg[i])
}
}
arg = args
}
}
target := msg.target
msg.target = s
msg.Hand = true
switch v := msg.Gdb("command", key, arg).(type) {
case string:
msg.Echo(v)
case nil:
if msg.Options("auto_cmd") {
if x.Auto != nil {
x.Auto(msg, c, key, arg...)
}
} else {
x.Hand(msg, c, key, arg...)
}
}
if msg.target == s {
msg.target = target
}
})
}
return msg.Hand
})
if !msg.Hand {
msg.Log("error", "cmd run error %s", msg.Format())
}
return msg
}
func (m *Message) Confm(key string, args ...interface{}) map[string]interface{} {
random := ""
var chain interface{}
if len(args) > 0 {
switch arg := args[0].(type) {
case []interface{}:
chain, args = arg, args[1:]
case []string:
chain, args = arg, args[1:]
case string:
switch arg {
case "%", "*":
random, args = arg, args[1:]
default:
chain, args = arg, args[1:]
}
}
}
var v interface{}
if chain == nil {
v = m.Confv(key)
} else {
v = m.Confv(key, chain)
}
table, _ := v.([]interface{})
value, _ := v.(map[string]interface{})
if len(args) == 0 {
return value
}
switch fun := args[0].(type) {
case func(int, string):
for i, v := range table {
fun(i, kit.Format(v))
}
case func(int, string) bool:
for i, v := range table {
if fun(i, kit.Format(v)) {
break
}
}
case func(string, string):
for k, v := range value {
fun(k, kit.Format(v))
}
case func(string, string) bool:
for k, v := range value {
if fun(k, kit.Format(v)) {
break
}
}
case func(map[string]interface{}):
if len(value) == 0 {
return nil
}
fun(value)
case func(string, map[string]interface{}):
switch random {
case "%":
n, i := rand.Intn(len(value)), 0
for k, v := range value {
if val, ok := v.(map[string]interface{}); i == n && ok {
fun(k, val)
break
}
i++
}
case "*":
fallthrough
default:
for k, v := range value {
if val, ok := v.(map[string]interface{}); ok {
fun(k, val)
}
}
}
case func(string, int, map[string]interface{}):
for k, v := range value {
if val, ok := v.([]interface{}); ok {
for i, v := range val {
if val, ok := v.(map[string]interface{}); ok {
fun(k, i, val)
}
}
}
}
case func(string, map[string]interface{}) bool:
for k, v := range value {
if val, ok := v.(map[string]interface{}); ok {
if fun(k, val) {
break
}
}
}
case func(int, map[string]interface{}):
for i := m.Optioni("page.begin"); i < len(table); i++ {
if val, ok := table[i].(map[string]interface{}); ok {
fun(i, val)
}
}
}
return value
}
func (m *Message) Confx(key string, args ...interface{}) string {
value := kit.Select(m.Conf(key), m.Option(key))
if len(args) == 0 {
return value
}
switch arg := args[0].(type) {
case []string:
if len(args) > 1 {
value = kit.Select(value, arg, args[1])
} else {
value = kit.Select(value, arg)
}
args = args[1:]
case map[string]interface{}:
value = kit.Select(value, kit.Format(arg[key]))
case string:
value = kit.Select(value, arg)
case nil:
default:
value = kit.Select(value, args[0])
}
format := "%s"
if args = args[1:]; len(args) > 0 {
format, args = kit.Format(args[0]), args[1:]
}
arg := []interface{}{format, value}
for _, v := range args {
arg = append(arg, v)
}
return kit.Format(arg...)
}
func (m *Message) Confs(key string, arg ...interface{}) bool {
return kit.Right(m.Confv(key, arg...))
}
func (m *Message) Confi(key string, arg ...interface{}) int {
return kit.Int(m.Confv(key, arg...))
}
func (m *Message) Confv(key string, args ...interface{}) interface{} {
if strings.Contains(key, ".") {
target := m.target
defer func() { m.target = target }()
ps := strings.Split(key, ".")
if msg := m.Sess(ps[0], false); msg != nil {
m.target, key = msg.target, ps[1]
}
}
var config *Config
m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
if x, ok := c.Configs[key]; ok {
config = x
return true
}
return false
})
if len(args) == 0 {
if config == nil {
return nil
}
return config.Value
}
if config == nil {
config = &Config{}
m.target.Configs[key] = config
}
switch config.Value.(type) {
case string:
config.Value = kit.Format(args...)
case bool:
config.Value = kit.Right(args...)
case int:
config.Value = kit.Int(args...)
case nil:
config.Value = args[0]
default:
for i := 0; i < len(args); i += 2 {
if i < len(args)-1 {
config.Value = kit.Chain(config.Value, args[i], args[i+1])
} else {
return kit.Chain(config.Value, args[i])
}
}
}
return config.Value
}
func (m *Message) Conf(key string, args ...interface{}) string {
return kit.Format(m.Confv(key, args...))
}
func (m *Message) Caps(key string, arg ...interface{}) bool {
if len(arg) > 0 {
return kit.Right(m.Cap(key, arg...))
}
return kit.Right(m.Cap(key))
}
func (m *Message) Capi(key string, arg ...interface{}) int {
n := kit.Int(m.Cap(key))
if len(arg) > 0 {
return kit.Int(m.Cap(key, n+kit.Int(arg...)))
}
return n
}
func (m *Message) Cap(key string, arg ...interface{}) string {
var cache *Cache
m.Match(key, false, func(m *Message, s *Context, c *Context, key string) bool {
if x, ok := c.Caches[key]; ok {
cache = x
return true
}
return false
})
if len(arg) == 0 {
if cache == nil {
return ""
}
if cache.Hand != nil {
return cache.Hand(m, cache)
}
return cache.Value
}
if cache == nil {
cache = &Cache{}
m.target.Caches[key] = cache
}
if cache.Hand != nil {
cache.Value = cache.Hand(m, cache, kit.Format(arg...))
} else {
cache.Value = kit.Format(arg...)
}
return cache.Value
}

660
src/contexts/ctx/what.go Normal file
View File

@ -0,0 +1,660 @@
package ctx
import (
"fmt"
"log"
"regexp"
"runtime"
"strings"
"sort"
"toolkit"
)
func (c *Context) Has(key ...string) bool {
switch len(key) {
case 2:
if _, ok := c.Commands[key[0]]; ok && key[1] == "command" {
return true
}
if _, ok := c.Configs[key[0]]; ok && key[1] == "config" {
return true
}
if _, ok := c.Caches[key[0]]; ok && key[1] == "cache" {
return true
}
case 1:
if _, ok := c.Commands[key[0]]; ok {
return true
}
if _, ok := c.Configs[key[0]]; ok {
return true
}
if _, ok := c.Caches[key[0]]; ok {
return true
}
}
return false
}
func (c *Context) Sub(key string) *Context {
return c.contexts[key]
}
func (c *Context) Travel(m *Message, hand func(m *Message, n int) (stop bool)) *Context {
if c == nil {
return nil
}
target := m.target
cs := []*Context{c}
for i := 0; i < len(cs); i++ {
if m.target = cs[i]; hand(m, i) {
return cs[i]
}
keys := []string{}
for k, _ := range cs[i].contexts {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
cs = append(cs, cs[i].contexts[k])
}
}
m.target = target
return target
}
func (c *Context) BackTrace(m *Message, hand func(m *Message) (stop bool)) *Context {
target := m.target
for s := m.target; s != nil; s = s.context {
if m.target = s; hand(m) {
return s
}
}
m.target = target
return target
}
func (m *Message) Format(arg ...interface{}) string {
if len(arg) == 0 {
arg = append(arg, "time", "ship")
}
meta := []string{}
for _, v := range arg {
switch kit.Format(v) {
case "summary":
msg := arg[1].(*Message)
ms := make([]*Message, 0, 1024)
ms = append(ms, msg.message, msg)
for i := 0; i < len(ms); i++ {
msg := ms[i]
if m.Add("append", "index", i); msg == nil {
m.Add("append", "message", "")
m.Add("append", "time", "")
m.Add("append", "code", "")
m.Add("append", "source", "")
m.Add("append", "target", "")
m.Add("append", "details", "")
m.Add("append", "options", "")
continue
}
if msg.message != nil {
m.Add("append", "message", msg.message.code)
} else {
m.Add("append", "message", "")
}
m.Add("append", "time", msg.time.Format("15:04:05"))
m.Add("append", "code", msg.code)
m.Add("append", "source", msg.source.Name)
m.Add("append", "target", msg.target.Name)
m.Add("append", "details", fmt.Sprintf("%v", msg.Meta["detail"]))
m.Add("append", "options", fmt.Sprintf("%v", msg.Meta["option"]))
if i == 0 {
continue
}
if len(ms) < 30 && len(arg) > 2 && arg[2] == "deep" {
ms = append(ms, ms[i].messages...)
}
}
m.Table()
case "time":
meta = append(meta, m.Time())
case "code":
meta = append(meta, kit.Format(m.code))
case "ship":
meta = append(meta, fmt.Sprintf("%s:%d(%s->%s)", m.Option("routine"), m.code, m.source.Name, m.target.Name))
case "source":
target := m.target
m.target = m.source
meta = append(meta, m.Cap("module"))
m.target = target
case "target":
meta = append(meta, m.Cap("module"))
case "detail":
meta = append(meta, fmt.Sprintf("%v", m.Meta["detail"]))
case "option":
meta = append(meta, fmt.Sprintf("%v", m.Meta["option"]))
case "append":
meta = append(meta, fmt.Sprintf("%v", m.Meta["append"]))
case "result":
meta = append(meta, fmt.Sprintf("%v", m.Meta["result"]))
case "full":
case "chain":
ms := []*Message{}
if v == "full" {
ms = append(ms, m)
} else {
for msg := m; msg != nil; msg = msg.message {
ms = append(ms, msg)
}
}
meta = append(meta, "\n")
for i := len(ms) - 1; i >= 0; i-- {
msg := ms[i]
meta = append(meta, fmt.Sprintf("%s\n", msg.Format("time", "ship")))
if len(msg.Meta["detail"]) > 0 {
meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"]))
}
if len(msg.Meta["option"]) > 0 {
meta = append(meta, fmt.Sprintf(" option: %d %v\n", len(msg.Meta["option"]), msg.Meta["option"]))
for _, k := range msg.Meta["option"] {
if v, ok := msg.Data[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
} else if v, ok := msg.Meta[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
}
}
}
if len(msg.Meta["append"]) > 0 {
meta = append(meta, fmt.Sprintf(" append: %d %v\n", len(msg.Meta["append"]), msg.Meta["append"]))
for _, k := range msg.Meta["append"] {
if v, ok := msg.Data[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v)))
} else if v, ok := msg.Meta[k]; ok {
meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v))
}
}
}
if len(msg.Meta["result"]) > 0 {
meta = append(meta, fmt.Sprintf(" result: %d %v\n", len(msg.Meta["result"]), msg.Meta["result"]))
}
}
case "stack":
pc := make([]uintptr, 100)
pc = pc[:runtime.Callers(6, pc)]
frames := runtime.CallersFrames(pc)
for {
frame, more := frames.Next()
file := strings.Split(frame.File, "/")
name := strings.Split(frame.Function, "/")
meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1]))
if !more {
break
}
}
default:
meta = append(meta, kit.FileName(kit.Format(v), "time"))
}
}
return strings.Join(meta, " ")
}
func (m *Message) Tree(code int) *Message {
ms := []*Message{m}
for i := 0; i < len(ms); i++ {
if ms[i].Code() == code {
return ms[i]
}
ms = append(ms, ms[i].messages...)
}
return nil
}
func (m *Message) Add(meta string, key string, value ...interface{}) *Message {
if m.Meta == nil {
m.Meta = make(map[string][]string)
}
if _, ok := m.Meta[meta]; !ok {
m.Meta[meta] = make([]string, 0, 3)
}
switch meta {
case "detail", "result":
m.Meta[meta] = append(m.Meta[meta], key)
m.Meta[meta] = append(m.Meta[meta], kit.Trans(value...)...)
case "option", "append":
if _, ok := m.Meta[key]; !ok {
m.Meta[key] = make([]string, 0, 3)
}
m.Meta[key] = append(m.Meta[key], kit.Trans(value...)...)
for _, v := range m.Meta[meta] {
if v == key {
return m
}
}
m.Meta[meta] = append(m.Meta[meta], key)
default:
m.Log("error", "add meta error %s %s %v", meta, key, value)
}
return m
}
func (m *Message) Set(meta string, arg ...interface{}) *Message {
switch meta {
case "detail", "result":
if m != nil && m.Meta != nil {
delete(m.Meta, meta)
}
case "option", "append":
if len(arg) > 0 {
delete(m.Meta, kit.Format(arg[0]))
} else {
for _, k := range m.Meta[meta] {
delete(m.Data, k)
delete(m.Meta, k)
}
delete(m.Meta, meta)
}
default:
m.Log("error", "set meta error %s %s %v", meta, arg)
}
if args := kit.Trans(arg...); len(args) > 0 {
m.Add(meta, args[0], args[1:])
}
return m
}
func (m *Message) Put(meta string, key string, value interface{}) *Message {
switch meta {
case "option", "append":
if m.Set(meta, key); m.Data == nil {
m.Data = make(map[string]interface{})
}
m.Data[key] = value
default:
m.Log("error", "put data error %s %s %v", meta, key, value)
}
return m
}
func (m *Message) Get(key string, arg ...interface{}) string {
if meta, ok := m.Meta[key]; ok && len(meta) > 0 {
index := 0
if len(arg) > 0 {
index = kit.Int(arg[0])
}
index = (index+2)%(len(meta)+2) - 2
if index >= 0 && index < len(meta) {
return meta[index]
}
}
return ""
}
func (m *Message) Has(key ...string) bool {
switch len(key) {
case 1:
if _, ok := m.Data[key[0]]; ok {
return true
}
if _, ok := m.Meta[key[0]]; ok {
return true
}
}
return false
}
func (m *Message) CopyTo(msg *Message, arg ...string) *Message {
msg.Copy(m, "append").Copy(m, "result")
return m
}
func (m *Message) CopyFuck(msg *Message, arg ...string) *Message {
if m == msg {
return m
}
for i := 0; i < len(arg); i++ {
meta := arg[i]
switch meta {
case "target":
m.target = msg.target
case "callback":
m.callback = msg.callback
case "detail", "result":
if len(msg.Meta[meta]) > 0 {
m.Add(meta, msg.Meta[meta][0], msg.Meta[meta][1:])
}
case "option", "append":
if msg.Meta == nil {
msg.Meta = map[string][]string{}
}
if msg.Meta[meta] == nil {
break
}
if i == len(arg)-1 {
arg = append(arg, msg.Meta[meta]...)
}
for i++; i < len(arg); i++ {
if v, ok := msg.Data[arg[i]]; ok {
m.Put(meta, arg[i], v)
} else if v, ok := msg.Meta[arg[i]]; ok {
m.Add(meta, arg[i], v) // TODO fuck Add
}
}
default:
if msg.Hand {
meta = "append"
} else {
meta = "option"
}
if v, ok := msg.Data[arg[i]]; ok {
m.Put(meta, arg[i], v)
}
if v, ok := msg.Meta[arg[i]]; ok {
m.Add(meta, arg[i], v)
}
}
}
return m
}
func (m *Message) Auto(arg ...string) *Message {
for i := 0; i < len(arg); i += 3 {
m.Add("append", "value", arg[i])
m.Add("append", "name", arg[i+1])
m.Add("append", "help", arg[i+2])
}
return m
}
func (m *Message) Insert(meta string, index int, arg ...interface{}) string {
if m.Meta == nil {
m.Meta = make(map[string][]string)
}
m.Meta[meta] = kit.Array(m.Meta[meta], index, arg)
if -1 < index && index < len(m.Meta[meta]) {
return m.Meta[meta][index]
}
return ""
}
func (m *Message) Magic(begin string, chain interface{}, args ...interface{}) interface{} {
auth := []string{"bench", "session", "user", "role", "componet", "command"}
key := []string{"bench", "sessid", "username", "role", "componet", "command"}
aaa := m.Sess("aaa", false)
for i, v := range auth {
if v == begin {
h := m.Option(key[i])
if v == "user" {
h, _ = kit.Hash("username", m.Option("username"))
}
data := aaa.Confv("auth", []string{h, "data"})
if kit.Format(chain) == "" {
return data
}
if len(args) > 0 {
value := kit.Chain(data, chain, args[0])
aaa.Conf("auth", []string{m.Option(key[i]), "data"}, value)
return value
}
value := kit.Chain(data, chain)
if value != nil {
return value
}
if i < len(auth)-1 {
begin = auth[i+1]
}
}
}
return nil
}
func (m *Message) Current(text string) string {
cs := []string{}
if pod := kit.Format(m.Magic("session", "current.pod")); pod != "" {
cs = append(cs, "context", "ssh", "remote", "'"+pod+"'")
}
if ctx := kit.Format(m.Magic("session", "current.ctx")); ctx != "" {
cs = append(cs, "context", ctx)
}
if cmd := kit.Format(m.Magic("session", "current.cmd")); cmd != "" {
cs = append(cs, cmd)
}
m.Log("info", "%s %s current %v", m.Option("username"), m.Option("sessid"), cs)
cs = append(cs, text)
return strings.Join(cs, " ")
}
func (m *Message) Parse(arg interface{}) string {
switch str := arg.(type) {
case string:
if len(str) > 1 && str[0] == '$' {
return m.Cap(str[1:])
}
if len(str) > 1 && str[0] == '@' {
if v := m.Option(str[1:]); v != "" {
return v
}
if v := kit.Format(m.Magic("bench", str[1:])); v != "" {
return v
}
v := m.Conf(str[1:])
return v
}
return str
}
return ""
}
func (m *Message) ToHTML(style string) string {
cmd := strings.Join(m.Meta["detail"], " ")
result := []string{}
if len(m.Meta["append"]) > 0 {
result = append(result, fmt.Sprintf("<table class='%s'>", style))
result = append(result, "<caption>", cmd, "</caption>")
m.Table(func(line int, maps map[string]string) {
if line == 0 {
result = append(result, "<tr>")
for _, v := range m.Meta["append"] {
result = append(result, "<th>", v, "</th>")
}
result = append(result, "</tr>")
return
}
result = append(result, "<tr>")
for _, k := range m.Meta["append"] {
result = append(result, "<td>", maps[k], "</td>")
}
result = append(result, "</tr>")
})
result = append(result, "</table>")
} else {
result = append(result, "<pre><code>")
result = append(result, fmt.Sprintf("%s", m.Find("shy", false).Conf("prompt")), cmd, "\n")
result = append(result, m.Meta["result"]...)
result = append(result, "</code></pre>")
}
return strings.Join(result, "")
}
func (m *Message) Gdb(arg ...interface{}) interface{} {
if g := m.Sess("gdb", false); g != nil {
if gdb, ok := g.target.Server.(DEBUG); ok {
return gdb.Wait(m, arg...)
}
}
return nil
}
func (m *Message) Log(action string, str string, arg ...interface{}) *Message {
if m.Options("log.disable") {
return m
}
if l := m.Sess("log", false); l != nil {
if log, ok := l.target.Server.(LOGGER); ok {
if action == "error" {
log.Log(m, "error", "chain: %s", m.Format("chain"))
}
log.Log(m, action, str, arg...)
if action == "error" {
log.Log(m, "error", "stack: %s", m.Format("stack"))
}
return m
}
} else {
log.Printf(str, arg...)
}
if action == "error" {
kit.Log("error", fmt.Sprintf("chain: %s", m.Format("chain")))
kit.Log("error", fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...)))
kit.Log("error", fmt.Sprintf("stack: %s", m.Format("stack")))
}
return m
}
func (m *Message) Show(args ...interface{}) *Message {
if m.Option("cli.modal") == "action" {
fmt.Printf(kit.Format(args...))
} else if kit.STDIO != nil {
kit.STDIO.Show(args...)
}
return m
}
func (m *Message) GoLoop(msg *Message, hand ...func(msg *Message)) *Message {
m.Gos(msg, func(msg *Message) {
for {
hand[0](msg)
}
})
return m
}
func (m *Message) Start(name string, help string, arg ...string) bool {
return m.Set("detail", arg).target.Spawn(m, name, help).Begin(m).Start(m)
}
func (m *Message) Close(arg ...string) bool {
return m.Target().Close(m, arg...)
}
func (m *Message) Wait() bool {
if m.target.exit != nil {
return <-m.target.exit
}
return true
}
func (m *Message) Find(name string, root ...bool) *Message {
if name == "" {
return m.Spawn()
}
target := m.target.root
if len(root) > 0 && !root[0] {
target = m.target
}
cs := target.contexts
for _, v := range strings.Split(name, ".") {
if x, ok := cs[v]; ok {
target, cs = x, x.contexts
} else if target.Name == v {
continue
} else {
m.Log("error", "context not find %s", name)
return nil
}
}
if len(root) > 1 && root[1] {
m.target = target
return m
}
return m.Spawn(target)
}
func (m *Message) Search(key string, root ...bool) []*Message {
reg, e := regexp.Compile(key)
m.Assert(e)
target := m.target
if target == nil {
return []*Message{nil}
}
if len(root) > 0 && root[0] {
target = m.target.root
}
cs := make([]*Context, 0, 3)
target.Travel(m, func(m *Message, i int) bool {
if reg.MatchString(m.target.Name) || reg.FindString(m.target.Help) != "" {
m.Log("search", "%d %s match [%s]", len(cs), m.target.Name, key)
cs = append(cs, m.target)
}
return false
})
ms := make([]*Message, len(cs))
for i := 0; i < len(cs); i++ {
ms[i] = m.Spawn(cs[i])
}
if len(ms) == 0 {
ms = append(ms, nil)
}
return ms
}
func (m *Message) Match(key string, spawn bool, hand func(m *Message, s *Context, c *Context, key string) bool) *Message {
if m == nil {
return m
}
context := []*Context{m.target}
for _, v := range []string{"aaa", "ssh", "cli", "nfs"} {
if msg := m.Sess(v, false); msg != nil && msg.target != nil {
context = append(context, msg.target)
}
}
// if m.target.root != nil && m.target.root.Configs != nil && m.target.root.Configs["search"] != nil && m.target.root.Configs["search"].Value != nil {
// target := m.target
// for _, v := range kit.Trans(kit.Chain(m.target.root.Configs["search"].Value, "context")) {
// if t := m.Find(v, true, true); t != nil {
// kit.Log("error", "%v", t)
// // // context = append(context, t.target)
// }
// }
// m.target = target
// }
context = append(context, m.source)
for _, s := range context {
for c := s; c != nil; c = c.context {
if hand(m, s, c, key) {
return m
}
}
}
return m
}
func (m *Message) Backs(msg *Message) *Message {
m.Back(msg)
return msg
}

View File

@ -452,16 +452,13 @@ func (nfs *NFS) Auto(what []rune, trigger string, index int) (change bool, frame
} }
table = []map[string]string{} table = []map[string]string{}
m.Spawn(auto_target).Cmd(cmd...).Table(func(maps map[string]string, list []string, line int) bool { m.Spawn(auto_target).Cmd(cmd...).Table(func(line int, maps map[string]string) {
if line >= 0 { fields := []interface{}{}
fields := []interface{}{} for _, v := range auto["fields"].([]interface{}) {
for _, v := range auto["fields"].([]interface{}) { fields = append(fields, maps[kit.Format(v)])
fields = append(fields, maps[kit.Format(v)])
}
maps["format"] = fmt.Sprintf(kit.Format(auto["format"]), fields...)
table = append(table, maps)
} }
return true maps["format"] = fmt.Sprintf(kit.Format(auto["format"]), fields...)
table = append(table, maps)
}) })
m.Conf("term", []interface{}{"help_table", auto["table"]}, table) m.Conf("term", []interface{}{"help_table", auto["table"]}, table)
@ -996,14 +993,14 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool {
if head == "detail" { // 接收请求 if head == "detail" { // 接收请求
msg.Detail(-1, "_route") msg.Detail(-1, "_route")
msg.Option("remote_code", code) msg.Option("remote_code", code)
m.GoFunc(msg, func(msg *ctx.Message) { m.Gos(msg, func(msg *ctx.Message) {
msg.Call(func(msg *ctx.Message) *ctx.Message { msg.Call(func(msg *ctx.Message) *ctx.Message {
nfs.echo <- msg nfs.echo <- msg
return nil return nil
}) })
}) })
} else { // 接收响应 } else { // 接收响应
m.Set("option", "code", code).GoFunc(msg, func(msg *ctx.Message) { m.Set("option", "code", code).Gos(msg, func(msg *ctx.Message) {
if h, ok := nfs.hand[kit.Int(m.Option("code"))]; ok { if h, ok := nfs.hand[kit.Int(m.Option("code"))]; ok {
h.CopyFuck(msg, "result").CopyFuck(msg, "append").Back(h) h.CopyFuck(msg, "result").CopyFuck(msg, "append").Back(h)
} }
@ -1405,7 +1402,9 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心",
for _, from := range arg[1:] { for _, from := range arg[1:] {
f, e := os.Open(from) f, e := os.Open(from)
m.Assert(e) if e != nil {
continue
}
defer f.Close() defer f.Close()
n, e := io.Copy(to, f) n, e := io.Copy(to, f)

View File

@ -164,9 +164,10 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
"favor": []interface{}{ "favor": []interface{}{
map[string]interface{}{"componet_name": "clip", "componet_help": "粘贴板", map[string]interface{}{"componet_name": "clip", "componet_help": "粘贴板",
"componet_tmpl": "componet", "componet_view": "Context", "componet_init": "", "componet_tmpl": "componet", "componet_view": "Context", "componet_init": "",
"componet_type": "public", "componet_ctx": "aaa", "componet_cmd": "clip", "componet_type": "public", "componet_ctx": "ssh", "componet_cmd": "_route",
"componet_args": []interface{}{}, "inputs": []interface{}{ "componet_args": []interface{}{"$$", "context", "aaa", "clip"}, "inputs": []interface{}{
map[string]interface{}{"type": "text", "name": "content", "view": "long"}, map[string]interface{}{"type": "text", "name": "you", "imports": "plugin_you"},
map[string]interface{}{"type": "text", "name": "txt", "view": "long"},
map[string]interface{}{"type": "button", "value": "运行"}, map[string]interface{}{"type": "button", "value": "运行"},
}, },
}, },

View File

@ -25,7 +25,7 @@ func (tcp *TCP) Fuck(address []string, action func(address string) (net.Conn, er
for i := 0; i < m.Confi("retry", "counts"); i++ { for i := 0; i < m.Confi("retry", "counts"); i++ {
for _, p := range address { for _, p := range address {
m.Cap("address", p) m.Cap("address", p)
m.GoFunc(m, func(m *ctx.Message) { m.Gos(m, func(m *ctx.Message) {
p := m.Cap("address") p := m.Cap("address")
if c, e := action(p); e == nil { if c, e := action(p); e == nil {
tcp.Conn = c tcp.Conn = c

View File

@ -1,30 +0,0 @@
package main
import (
// 数据层
_ "contexts/mdb" //数据中心
_ "contexts/nfs" //存储中心
_ "contexts/ssh" //集群中心
_ "contexts/tcp" //网络中心
// 控制层
_ "contexts/gdb" //调试中心
_ "contexts/lex" //词法中心
_ "contexts/log" //日志中心
_ "contexts/yac" //语法中心
// 服务层
_ "contexts/aaa" //认证中心
_ "contexts/cli" //管理中心
c "contexts/ctx" //模块中心
_ "contexts/web" //应用中心
// 应用层
_ "examples/chat" //会议中心
_ "examples/code" //代码中心
_ "examples/wiki" //文档中心
// _ "examples/jira" //任务中心
// _ "examples/mall" //交易中心
)
func main() {
c.Start()
}

View File

@ -1,83 +0,0 @@
package main
import (
"bufio"
"fmt"
"io"
"os"
"regexp"
"toolkit"
)
var files = ".*\\.(xml|html|css|js)$"
var words = "[[:^ascii:]]+"
func main() {
if len(os.Args) == 1 {
fmt.Println("usage", os.Args[0], "dirs [files [words]]")
fmt.Println("在目录dirs中查找匹配files的文件并查找匹配words的单词")
os.Exit(1)
}
if len(os.Args) > 2 {
files = os.Args[2]
}
if len(os.Args) > 3 {
words = os.Args[3]
}
word, e := regexp.Compile(words)
kit.Check(e)
// out, e := os.Create(os.Args[2])
// kit.Check(e)
out := os.Stdout
total := 0
count := 0
chars := 0
kit.DirWalk(os.Args[1], func(file string) {
s, _ := os.Stat(file)
if s.IsDir() {
return
}
if m, e := regexp.MatchString(files, file); !kit.Check(e) || !m {
return
}
f, e := os.Open(file)
kit.Check(e)
bio := bufio.NewReader(f)
fmt.Fprintln(out, kit.FmtSize(s.Size()), file)
line := 0
cs := 0
for i := 1; true; i++ {
l, e := bio.ReadString('\n')
if e == io.EOF {
break
}
kit.Check(e)
if i == 1 {
continue
}
a := word.FindAllString(l, 20)
for _, v := range a {
n := len([]rune(v))
fmt.Fprintf(out, "l:%d c:%d %s\n", i, n, v)
total++
line++
chars += n
cs += n
}
}
fmt.Fprintln(out, "lines:", line, "chars:", cs, file)
fmt.Fprintln(out)
if line > 0 {
count++
}
})
fmt.Fprintln(out, "files:", count, "lines:", total, "chars:", chars, os.Args[1])
return
}

View File

@ -1,68 +0,0 @@
package main
import (
"bufio"
"bytes"
"fmt"
"io"
"net/http"
"os"
"path"
"strings"
"time"
)
func main() {
if len(os.Args) < 3 {
fmt.Printf("usage: %s file server", os.Args[0])
return
}
prefix0 := len("uri[")
prefix1 := len("request_param[")
if os.Mkdir("tmp", 0777) != nil {
}
begin := time.Now()
f, e := os.Open(os.Args[1])
if e != nil {
fmt.Printf("%s\n", e)
os.Exit(1)
}
defer f.Close()
bio := bufio.NewScanner(f)
output := map[string]*os.File{}
nreq := 0
for bio.Scan() {
word := strings.Split(bio.Text(), " ")
if len(word) != 2 {
continue
}
uri := word[0][prefix0:len(word[0])-1]
arg := word[1][prefix1:len(word[1])-1]
if output[uri] == nil {
name := path.Join("tmp", strings.Replace(uri, "/", "_", -1)+".txt")
f, e = os.Create(name)
output[uri] = f
}
nreq++
br := bytes.NewReader([]byte(arg))
fmt.Printf("%d post: %v\n", nreq, os.Args[2]+uri)
res, e := http.Post(os.Args[2]+uri, "application/json", br)
fmt.Fprintf(output[uri], uri)
fmt.Fprintf(output[uri], " arguments:")
fmt.Fprintf(output[uri], arg)
fmt.Fprintf(output[uri], " result:")
if e != nil {
fmt.Fprintf(output[uri], "%v", e)
} else if res.StatusCode != http.StatusOK {
fmt.Fprintf(output[uri], res.Status)
} else {
io.Copy(output[uri], res.Body)
}
fmt.Fprintf(output[uri], "\n")
}
fmt.Printf("nuri: %v nreq: %v cost: %v", len(output), nreq, time.Since(begin))
}

View File

@ -153,11 +153,10 @@ var Index = &ctx.Context{Name: "wiki", Help: "文档中心",
m.Sort(sort_field, sort_order).Table() m.Sort(sort_field, sort_order).Table()
m.Target().Configs["wiki_list"].Value = []interface{}{} m.Target().Configs["wiki_list"].Value = []interface{}{}
m.Table(func(maps map[string]string, list []string, line int) bool { m.Table(func(line int, maps map[string]string) {
if line > 0 { if line > 1 {
m.Confv("wiki_list", -2, maps) m.Confv("wiki_list", -2, maps)
} }
return true
}) })
return return
}}, }},

298
src/toolkit/core.go Normal file
View File

@ -0,0 +1,298 @@
package kit
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
var DisableLog = false
func Env(key string) {
os.Getenv(key)
}
func Log(action string, str string, args ...interface{}) {
if DisableLog {
return
}
if len(args) > 0 {
str = fmt.Sprintf(str, args...)
}
fmt.Fprintf(os.Stderr, "%s: %s\n", action, str)
}
func Errorf(str string, args ...interface{}) {
Log("error", str, args...)
}
func Debugf(str string, args ...interface{}) {
Log("debug", str, args...)
}
func Time(arg ...string) int {
if len(arg) == 0 {
return Int(time.Now())
}
if len(arg) > 1 {
if t, e := time.ParseInLocation(arg[1], arg[0], time.Local); e == nil {
return Int(t)
}
}
for _, v := range []string{
"2006-01-02 15:04:05",
"2006-01-02 15:04",
"2006-01-02",
"2006/01/02",
"01-02 15:04",
} {
if t, e := time.ParseInLocation(v, arg[0], time.Local); e == nil {
return Int(t)
}
}
return 0
}
func Duration(arg ...string) time.Duration {
d, _ := time.ParseDuration(arg[0])
return d
}
func Hash(arg ...interface{}) (string, []string) {
args := []string{}
for _, v := range Trans(arg...) {
switch v {
case "time":
args = append(args, Format(time.Now()))
case "rand":
args = append(args, Format(rand.Int()))
case "uniq":
args = append(args, Format(time.Now()))
args = append(args, Format(rand.Int()))
default:
if s, e := os.Stat(v); e == nil && !s.IsDir() {
if f, e := os.Open(v); e == nil {
defer f.Close()
m := md5.New()
io.Copy(m, f)
h := m.Sum(nil)
args = append(args, hex.EncodeToString(h[:]))
return hex.EncodeToString(h[:]), args
}
}
args = append(args, v)
}
}
h := md5.Sum([]byte(strings.Join(args, "")))
return hex.EncodeToString(h[:]), args
}
func Hashs(arg ...interface{}) string {
h, _ := Hash(arg...)
return h
}
func Chain(root interface{}, args ...interface{}) interface{} {
for i := 0; i < len(args); i += 2 {
if arg, ok := args[i].(map[string]interface{}); ok {
argn := []interface{}{}
for k, v := range arg {
argn = append(argn, k, v)
}
argn = append(argn, args[i+1:])
args, i = argn, -2
continue
}
var parent interface{}
parent_key, parent_index := "", 0
keys := []string{}
for _, v := range Trans(args[i]) {
keys = append(keys, strings.Split(v, ".")...)
}
data := root
for j, key := range keys {
index, e := strconv.Atoi(key)
// Log("error", "chain [%v %v] [%v %v] [%v/%v %v/%v] %v", parent_key, parent_index, key, index, i, len(args), j, len(keys), data)
var next interface{}
switch value := data.(type) {
case nil:
if i == len(args)-1 {
return nil
}
if j == len(keys)-1 {
next = args[i+1]
}
if e == nil {
data, index = []interface{}{next}, 0
} else {
data = map[string]interface{}{key: next}
}
case []string:
index = (index+2+len(value)+2)%(len(value)+2) - 2
if j == len(keys)-1 {
if i == len(args)-1 {
if index < 0 {
return ""
}
return value[index]
}
next = args[i+1]
}
if index == -1 {
data, index = append([]string{Format(next)}, value...), 0
} else {
data, index = append(value, Format(next)), len(value)
}
next = value[index]
case map[string]string:
if j == len(keys)-1 {
if i == len(args)-1 {
return value[key] // 读取数据
}
value[key] = Format(next) // 修改数据
}
next = value[key]
case map[string]interface{}:
if j == len(keys)-1 {
if i == len(args)-1 {
return value[key] // 读取数据
}
value[key] = args[i+1] // 修改数据
if !Right(args[i+1]) {
delete(value, key)
}
}
next = value[key]
case []interface{}:
index = (index+2+len(value)+2)%(len(value)+2) - 2
if j == len(keys)-1 {
if i == len(args)-1 {
if index < 0 {
return nil
}
return value[index] // 读取数据
}
next = args[i+1] // 修改数据
}
if index == -1 {
value, index = append([]interface{}{next}, value...), 0
} else if index == -2 {
value, index = append(value, next), len(value)
} else if j == len(keys)-1 {
value[index] = next
}
data, next = value, value[index]
}
switch p := parent.(type) {
case map[string]interface{}:
p[parent_key] = data
case []interface{}:
p[parent_index] = data
case nil:
root = data
}
parent, data = data, next
parent_key, parent_index = key, index
}
}
return root
}
func Chains(root interface{}, args ...interface{}) string {
return Format(Chain(root, args...))
}
func Select(value string, args ...interface{}) string {
if len(args) == 0 {
return value
}
switch arg := args[0].(type) {
case string:
if len(args) > 1 {
switch b := args[1].(type) {
case bool:
if b && arg != "" {
return arg
}
return value
}
}
if arg != "" {
return arg
}
case []interface{}:
index := 0
if len(args) > 1 {
index = Int(args[1])
}
if index < len(arg) && Format(arg[index]) != "" {
return Format(arg[index])
}
case []string:
index := 0
if len(args) > 1 {
index = Int(args[1])
}
if index < len(arg) && arg[index] != "" {
return arg[index]
}
default:
if v := Format(args...); v != "" {
return v
}
}
return value
}
func Slice(arg []string, args ...interface{}) ([]string, string) {
if len(arg) == 0 {
return arg, ""
}
if len(args) == 0 {
return arg[1:], arg[0]
}
result := ""
switch v := args[0].(type) {
case int:
case string:
if arg[0] == v && len(arg) > 1 {
return arg[2:], arg[1]
}
if len(args) > 1 {
return arg, Format(args[1])
}
}
return arg, result
}
func View(args []string, conf map[string]interface{}) []string {
if len(args) == 0 {
args = append(args, "default")
}
keys := []string{}
for _, k := range args {
if v, ok := conf[k]; ok {
keys = append(keys, Trans(v)...)
} else {
keys = append(keys, k)
}
}
return keys
}

View File

@ -1,764 +0,0 @@
package kit
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"strconv"
"strings"
"io/ioutil"
"math/rand"
"os"
"path"
"time"
)
type TERM interface {
Show(...interface{}) bool
}
var STDIO TERM
var DisableLog = false
var EnableDebug = false
func Log(action string, str string, args ...interface{}) {
if DisableLog {
return
}
if len(args) > 0 {
str = fmt.Sprintf(str, args...)
}
fmt.Fprintf(os.Stderr, "%s: %s\n", action, str)
}
func Errorf(str string, args ...interface{}) {
Log("error", str, args...)
}
func Debugf(str string, args ...interface{}) {
Log("debug", str, args...)
}
func Key(name string) string {
return strings.Replace(name, ".", "_", -1)
}
func Env(key string) {
os.Getenv(key)
}
func Width(str string, mul int) int {
return len([]rune(str)) + (len(str)-len([]rune(str)))/2/mul
}
func Len(arg interface{}) int {
switch arg := arg.(type) {
case []interface{}:
return len(arg)
case map[string]interface{}:
return len(arg)
}
return 0
}
func Int(arg ...interface{}) int {
result := 0
for _, v := range arg {
switch val := v.(type) {
case int:
result += val
case int8:
result += int(val)
case int16:
result += int(val)
// case int32:
// result += int(val)
case int64:
result += int(val)
// case uint8:
// result += int(val)
case uint16:
result += int(val)
case uint32:
result += int(val)
case uint64:
result += int(val)
case float64:
result += int(val)
case byte: // uint8
result += int(val)
case rune: // int32
result += int(val)
case string:
if i, e := strconv.Atoi(val); e == nil {
result += i
}
case bool:
if val {
result += 1
}
case time.Time:
result += int(val.Unix())
case []string:
result += len(val)
case map[string]string:
result += len(val)
case []interface{}:
result += len(val)
case map[string]interface{}:
result += len(val)
}
}
return result
}
func Int64(arg ...interface{}) int64 {
var result int64
for _, v := range arg {
switch val := v.(type) {
case int:
result += int64(val)
case int8:
result += int64(val)
case int16:
result += int64(val)
// case int32:
// result += int64(val)
case int64:
result += int64(val)
// case uint8:
// result += int64(val)
case uint16:
result += int64(val)
case uint32:
result += int64(val)
case uint64:
result += int64(val)
case float64:
result += int64(val)
case byte: // uint8
result += int64(val)
case rune: // int32
result += int64(val)
case string:
if i, e := strconv.ParseInt(val, 10, 64); e == nil {
result += i
}
case bool:
if val {
result += 1
}
case time.Time:
result += int64(val.Unix())
case []string:
result += int64(len(val))
case map[string]string:
result += int64(len(val))
case []interface{}:
result += int64(len(val))
case map[string]interface{}:
result += int64(len(val))
}
}
return result
}
func Right(arg ...interface{}) bool {
result := false
for _, v := range arg {
switch val := v.(type) {
case int:
result = result || val != 0
case bool:
result = result || val
case string:
switch val {
case "", "0", "false", "off", "no", "error: ":
result = result || false
default:
result = result || true
}
case error:
result = result || false
case []string:
result = result || len(val) > 0
case map[string]string:
result = result || len(val) > 0
case []interface{}:
result = result || len(val) > 0
case map[string]interface{}:
result = result || len(val) > 0
default:
result = result || val != nil
}
}
return result
}
func Format(arg ...interface{}) string {
result := []string{}
for _, v := range arg {
switch val := v.(type) {
case nil:
result = result[:0]
case int, int8, int16, int32, int64:
result = append(result, fmt.Sprintf("%d", val))
case uint, uint8, uint16, uint32, uint64:
result = append(result, fmt.Sprintf("%d", val))
case float64:
result = append(result, fmt.Sprintf("%d", int(val)))
case bool:
result = append(result, fmt.Sprintf("%t", val))
case string:
result = append(result, val)
case []byte:
result = append(result, string(val))
case []rune:
result = append(result, string(val))
case []string:
result = append(result, val...)
// case []interface{}:
//
// result = append(result, "[")
// for i, value := range val {
// result = append(result, Format(value))
// if i < len(val)-1 {
// result = append(result, ",")
// }
// }
// result = append(result, "]")
case time.Time:
result = append(result, fmt.Sprintf("%s", val.Format("2006-01-02 15:03:04")))
case *os.File:
if s, e := val.Stat(); e == nil {
result = append(result, fmt.Sprintf("%T [name: %s]", v, s.Name()))
} else {
result = append(result, fmt.Sprintf("%T", v))
}
// case error:
// result = append(result, fmt.Sprintf("%v", val))
default:
if b, e := json.Marshal(val); e == nil {
result = append(result, string(b))
}
}
}
if len(result) > 1 {
args := []interface{}{}
if n := strings.Count(result[0], "%") - strings.Count(result[0], "%%"); len(result) > n {
for i := 1; i < n+1; i++ {
args = append(args, result[i])
}
return fmt.Sprintf(result[0], args...) + strings.Join(result[n+1:], "")
} else if len(result) == n+1 {
for i := 1; i < len(result); i++ {
args = append(args, result[i])
}
return fmt.Sprintf(result[0], args...)
}
}
return strings.Join(result, "")
}
func Simple(str string) string {
return strings.Replace(strings.TrimSpace(str), "\n", "\\n", -1)
}
func Formats(arg ...interface{}) string {
result := []string{}
for _, v := range arg {
switch val := v.(type) {
// case []interface{}:
// for _, v := range val {
// result = append(result, Format(v))
// }
default:
if b, e := json.MarshalIndent(val, "", " "); e == nil {
result = append(result, string(b))
} else {
result = append(result, fmt.Sprintf("%#v", val))
}
}
}
return strings.Join(result, " ")
}
func Trans(arg ...interface{}) []string {
ls := []string{}
for _, v := range arg {
switch val := v.(type) {
// case *Message:
// if val.Hand {
// ls = append(ls, val.Meta["result"]...)
// } else {
// ls = append(ls, val.Meta["detail"]...)
// }
case nil:
case []float64:
for _, v := range val {
ls = append(ls, fmt.Sprintf("%d", int(v)))
}
case []int:
for _, v := range val {
ls = append(ls, fmt.Sprintf("%d", v))
}
case []bool:
for _, v := range val {
ls = append(ls, fmt.Sprintf("%t", v))
}
case []string:
ls = append(ls, val...)
case map[string]string:
for k, v := range val {
ls = append(ls, k, v)
}
case map[string]interface{}:
for k, v := range val {
ls = append(ls, k, Format(v))
}
case []interface{}:
for _, v := range val {
ls = append(ls, Format(v))
}
default:
ls = append(ls, Format(val))
}
}
return ls
}
func Struct(arg ...interface{}) map[string]interface{} {
value := map[string]interface{}{}
if len(arg) == 0 {
return value
}
switch val := arg[0].(type) {
case map[string]interface{}:
return val
case string:
json.Unmarshal([]byte(val), value)
}
return value
}
func Structm(args ...interface{}) map[string]interface{} {
value := Struct(args...)
for _, arg := range args {
switch val := arg.(type) {
case func(k string, v string):
for k, v := range value {
val(k, Format(v))
}
}
}
return value
}
func Array(list []string, index int, arg ...interface{}) []string {
if len(arg) == 0 {
if -1 < index && index < len(list) {
return []string{list[index]}
}
return []string{""}
}
str := Trans(arg...)
index = (index+2)%(len(list)+2) - 2
if index == -1 {
list = append(str, list...)
} else if index == -2 {
list = append(list, str...)
} else {
if index < -2 {
index += len(list) + 2
}
if index < 0 {
index = 0
}
for i := len(list); i < index+len(str); i++ {
list = append(list, "")
}
for i := 0; i < len(str); i++ {
list[index+i] = str[i]
}
}
return list
}
func Slice(arg []string, args ...interface{}) ([]string, string) {
if len(arg) == 0 {
return arg, ""
}
if len(args) == 0 {
return arg[1:], arg[0]
}
result := ""
switch v := args[0].(type) {
case int:
case string:
if arg[0] == v && len(arg) > 1 {
return arg[2:], arg[1]
}
if len(args) > 1 {
return arg, Format(args[1])
}
}
return arg, result
}
func Elect(last interface{}, args ...interface{}) string {
if len(args) > 0 {
switch arg := args[0].(type) {
case []string:
index := 0
if len(args) > 1 {
switch a := args[1].(type) {
case string:
i, e := strconv.Atoi(a)
if e == nil {
index = i
}
case int:
index = a
}
}
if 0 <= index && index < len(arg) && arg[index] != "" {
return arg[index]
}
case string:
if arg != "" {
return arg
}
}
}
switch l := last.(type) {
case string:
return l
}
return ""
}
func Select(value string, args ...interface{}) string {
if len(args) == 0 {
return value
}
switch arg := args[0].(type) {
case string:
if len(args) > 1 {
switch b := args[1].(type) {
case bool:
if b && arg != "" {
return arg
}
return value
}
}
if arg != "" {
return arg
}
case []interface{}:
index := 0
if len(args) > 1 {
index = Int(args[1])
}
if index < len(arg) && Format(arg[index]) != "" {
return Format(arg[index])
}
case []string:
index := 0
if len(args) > 1 {
index = Int(args[1])
}
if index < len(arg) && arg[index] != "" {
return arg[index]
}
default:
if v := Format(args...); v != "" {
return v
}
}
return value
}
func Chain(root interface{}, args ...interface{}) interface{} {
for i := 0; i < len(args); i += 2 {
if arg, ok := args[i].(map[string]interface{}); ok {
argn := []interface{}{}
for k, v := range arg {
argn = append(argn, k, v)
}
argn = append(argn, args[i+1:])
args, i = argn, -2
continue
}
var parent interface{}
parent_key, parent_index := "", 0
keys := []string{}
for _, v := range Trans(args[i]) {
keys = append(keys, strings.Split(v, ".")...)
}
data := root
for j, key := range keys {
index, e := strconv.Atoi(key)
// Log("error", "chain [%v %v] [%v %v] [%v/%v %v/%v] %v", parent_key, parent_index, key, index, i, len(args), j, len(keys), data)
var next interface{}
switch value := data.(type) {
case nil:
if i == len(args)-1 {
return nil
}
if j == len(keys)-1 {
next = args[i+1]
}
if e == nil {
data, index = []interface{}{next}, 0
} else {
data = map[string]interface{}{key: next}
}
case []string:
index = (index+2+len(value)+2)%(len(value)+2) - 2
if j == len(keys)-1 {
if i == len(args)-1 {
if index < 0 {
return ""
}
return value[index]
}
next = args[i+1]
}
if index == -1 {
data, index = append([]string{Format(next)}, value...), 0
} else {
data, index = append(value, Format(next)), len(value)
}
next = value[index]
case map[string]string:
if j == len(keys)-1 {
if i == len(args)-1 {
return value[key] // 读取数据
}
value[key] = Format(next) // 修改数据
}
next = value[key]
case map[string]interface{}:
if j == len(keys)-1 {
if i == len(args)-1 {
return value[key] // 读取数据
}
value[key] = args[i+1] // 修改数据
if !Right(args[i+1]) {
delete(value, key)
}
}
next = value[key]
case []interface{}:
index = (index+2+len(value)+2)%(len(value)+2) - 2
if j == len(keys)-1 {
if i == len(args)-1 {
if index < 0 {
return nil
}
return value[index] // 读取数据
}
next = args[i+1] // 修改数据
}
if index == -1 {
value, index = append([]interface{}{next}, value...), 0
} else if index == -2 {
value, index = append(value, next), len(value)
} else if j == len(keys)-1 {
value[index] = next
}
data, next = value, value[index]
}
switch p := parent.(type) {
case map[string]interface{}:
p[parent_key] = data
case []interface{}:
p[parent_index] = data
case nil:
root = data
}
parent, data = data, next
parent_key, parent_index = key, index
}
}
return root
}
func Chains(root interface{}, args ...interface{}) string {
return Format(Chain(root, args...))
}
func View(args []string, conf map[string]interface{}) []string {
if len(args) == 0 {
args = append(args, "default")
}
keys := []string{}
for _, k := range args {
if v, ok := conf[k]; ok {
keys = append(keys, Trans(v)...)
} else {
keys = append(keys, k)
}
}
return keys
}
func Link(name string, url string) string {
return fmt.Sprintf("<a href=\"%s\" target=\"_blank\">%s</a>", url, name)
}
func Time(arg ...string) int {
if len(arg) == 0 {
return Int(time.Now())
}
if len(arg) > 1 {
if t, e := time.ParseInLocation(arg[1], arg[0], time.Local); e == nil {
return Int(t)
}
}
for _, v := range []string{
"2006-01-02 15:04:05",
"2006-01-02 15:04",
"2006-01-02",
"2006/01/02",
"01-02 15:04",
} {
if t, e := time.ParseInLocation(v, arg[0], time.Local); e == nil {
return Int(t)
}
}
return 0
}
func Duration(arg ...string) time.Duration {
d, _ := time.ParseDuration(arg[0])
return d
}
func FileName(name string, meta ...string) string {
result, app := strings.Split(name, "."), ""
if len(result) > 1 {
app, result = result[len(result)-1], result[:len(result)-1]
}
for _, v := range meta {
switch v {
case "year":
result = append(result, "_", time.Now().Format("2006"))
case "date":
result = append(result, "_", time.Now().Format("0102"))
case "time":
result = append(result, "_", time.Now().Format("2006_0102_1504"))
case "rand":
result = append(result, "_", Format(rand.Int()))
case "uniq":
result = append(result, "_", Format(Time()))
result = append(result, "_", Format(rand.Int()))
}
}
if app != "" {
result = append(result, ".", app)
}
return strings.Join(result, "")
}
func FmtSize(size uint64) string {
if size > 1<<30 {
return fmt.Sprintf("%d.%dG", size>>30, (size>>20)%1024*100/1024)
}
if size > 1<<20 {
return fmt.Sprintf("%d.%dM", size>>20, (size>>10)%1024*100/1024)
}
if size > 1<<10 {
return fmt.Sprintf("%d.%dK", size>>10, size%1024*100/1024)
}
return fmt.Sprintf("%dB", size)
}
func FmtNano(nano int64) string {
if nano > 1000000000 {
return fmt.Sprintf("%d.%ds", nano/1000000000, nano/100000000%100)
}
if nano > 1000000 {
return fmt.Sprintf("%d.%dms", nano/100000, nano/100000%100)
}
if nano > 1000 {
return fmt.Sprintf("%d.%dus", nano/1000, nano/100%100)
}
return fmt.Sprintf("%dns", nano)
}
func Hash(arg ...interface{}) (string, []string) {
args := []string{}
for _, v := range Trans(arg...) {
switch v {
case "time":
args = append(args, Format(time.Now()))
case "rand":
args = append(args, Format(rand.Int()))
case "uniq":
args = append(args, Format(time.Now()))
args = append(args, Format(rand.Int()))
default:
if s, e := os.Stat(v); e == nil && !s.IsDir() {
if f, e := os.Open(v); e == nil {
defer f.Close()
m := md5.New()
io.Copy(m, f)
h := m.Sum(nil)
args = append(args, hex.EncodeToString(h[:]))
return hex.EncodeToString(h[:]), args
}
}
args = append(args, v)
}
}
h := md5.Sum([]byte(strings.Join(args, "")))
return hex.EncodeToString(h[:]), args
}
func Hashs(arg ...interface{}) string {
h, _ := Hash(arg...)
return h
}
func Block(root interface{}, args ...interface{}) interface{} {
return root
}
func Check(e error) bool {
if e != nil {
panic(e)
}
return true
}
func DirWalk(file string, hand func(file string)) {
s, e := os.Stat(file)
Check(e)
hand(file)
if s.IsDir() {
fs, e := ioutil.ReadDir(file)
Check(e)
for _, v := range fs {
DirWalk(path.Join(file, v.Name()), hand)
}
}
}

246
src/toolkit/type.go Normal file
View File

@ -0,0 +1,246 @@
package kit
import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"time"
)
func Right(arg ...interface{}) bool {
result := false
for _, v := range arg {
switch val := v.(type) {
case int:
result = result || val != 0
case bool:
result = result || val
case string:
switch val {
case "", "0", "false", "off", "no", "error: ":
result = result || false
default:
result = result || true
}
case error:
result = result || false
case []string:
result = result || len(val) > 0
case map[string]string:
result = result || len(val) > 0
case []interface{}:
result = result || len(val) > 0
case map[string]interface{}:
result = result || len(val) > 0
default:
result = result || val != nil
}
}
return result
}
func Int64(arg ...interface{}) int64 {
var result int64
for _, v := range arg {
switch val := v.(type) {
case int:
result += int64(val)
case int8:
result += int64(val)
case int16:
result += int64(val)
// case int32:
// result += int64(val)
case int64:
result += int64(val)
// case uint8:
// result += int64(val)
case uint16:
result += int64(val)
case uint32:
result += int64(val)
case uint64:
result += int64(val)
case float64:
result += int64(val)
case byte: // uint8
result += int64(val)
case rune: // int32
result += int64(val)
case string:
if i, e := strconv.ParseInt(val, 10, 64); e == nil {
result += i
}
case bool:
if val {
result += 1
}
case time.Time:
result += int64(val.Unix())
case []string:
result += int64(len(val))
case map[string]string:
result += int64(len(val))
case []interface{}:
result += int64(len(val))
case map[string]interface{}:
result += int64(len(val))
}
}
return result
}
func Int(arg ...interface{}) int {
return int(Int64(arg...))
}
func Key(name string) string {
return strings.Replace(name, ".", "_", -1)
}
func Format(arg ...interface{}) string {
result := []string{}
for _, v := range arg {
switch val := v.(type) {
case nil:
result = result[:0]
case int, int8, int16, int32, int64:
result = append(result, fmt.Sprintf("%d", val))
case uint, uint8, uint16, uint32, uint64:
result = append(result, fmt.Sprintf("%d", val))
case float64:
result = append(result, fmt.Sprintf("%d", int(val)))
case bool:
result = append(result, fmt.Sprintf("%t", val))
case string:
result = append(result, val)
case []byte:
result = append(result, string(val))
case []rune:
result = append(result, string(val))
case []string:
result = append(result, val...)
// case []interface{}:
//
// result = append(result, "[")
// for i, value := range val {
// result = append(result, Format(value))
// if i < len(val)-1 {
// result = append(result, ",")
// }
// }
// result = append(result, "]")
case time.Time:
result = append(result, fmt.Sprintf("%s", val.Format("2006-01-02 15:03:04")))
case *os.File:
if s, e := val.Stat(); e == nil {
result = append(result, fmt.Sprintf("%T [name: %s]", v, s.Name()))
} else {
result = append(result, fmt.Sprintf("%T", v))
}
// case error:
// result = append(result, fmt.Sprintf("%v", val))
default:
if b, e := json.Marshal(val); e == nil {
result = append(result, string(b))
}
}
}
if len(result) > 1 {
args := []interface{}{}
if n := strings.Count(result[0], "%") - strings.Count(result[0], "%%"); len(result) > n {
for i := 1; i < n+1; i++ {
args = append(args, result[i])
}
return fmt.Sprintf(result[0], args...) + strings.Join(result[n+1:], "")
} else if len(result) == n+1 {
for i := 1; i < len(result); i++ {
args = append(args, result[i])
}
return fmt.Sprintf(result[0], args...)
}
}
return strings.Join(result, "")
}
func Formats(arg ...interface{}) string {
result := []string{}
for _, v := range arg {
switch val := v.(type) {
default:
if b, e := json.MarshalIndent(val, "", " "); e == nil {
result = append(result, string(b))
} else {
result = append(result, fmt.Sprintf("%#v", val))
}
}
}
return strings.Join(result, " ")
}
func Trans(arg ...interface{}) []string {
ls := []string{}
for _, v := range arg {
switch val := v.(type) {
// case *Message:
// if val.Hand {
// ls = append(ls, val.Meta["result"]...)
// } else {
// ls = append(ls, val.Meta["detail"]...)
// }
case nil:
case []float64:
for _, v := range val {
ls = append(ls, fmt.Sprintf("%d", int(v)))
}
case []int:
for _, v := range val {
ls = append(ls, fmt.Sprintf("%d", v))
}
case []bool:
for _, v := range val {
ls = append(ls, fmt.Sprintf("%t", v))
}
case []string:
ls = append(ls, val...)
case map[string]string:
for k, v := range val {
ls = append(ls, k, v)
}
case map[string]interface{}:
for k, v := range val {
ls = append(ls, k, Format(v))
}
case []interface{}:
for _, v := range val {
ls = append(ls, Format(v))
}
default:
ls = append(ls, Format(val))
}
}
return ls
}
func Struct(arg ...interface{}) map[string]interface{} {
value := map[string]interface{}{}
if len(arg) == 0 {
return value
}
switch val := arg[0].(type) {
case map[string]interface{}:
return val
case string:
json.Unmarshal([]byte(val), value)
}
return value
}
func Structm(args ...interface{}) map[string]interface{} {
value := Struct(args...)
for _, arg := range args {
switch val := arg.(type) {
case func(k string, v string):
for k, v := range value {
val(k, Format(v))
}
}
}
return value
}

190
src/toolkit/what.go Normal file
View File

@ -0,0 +1,190 @@
package kit
import (
"fmt"
"strconv"
"strings"
"io/ioutil"
"math/rand"
"os"
"path"
"time"
)
type TERM interface {
Show(...interface{}) bool
}
var STDIO TERM
var EnableDebug = false
func Width(str string, mul int) int {
return len([]rune(str)) + (len(str)-len([]rune(str)))/2/mul
}
func Len(arg interface{}) int {
switch arg := arg.(type) {
case []interface{}:
return len(arg)
case map[string]interface{}:
return len(arg)
}
return 0
}
func Simple(str string) string {
return strings.Replace(strings.TrimSpace(str), "\n", "\\n", -1)
}
func Array(list []string, index int, arg ...interface{}) []string {
if len(arg) == 0 {
if -1 < index && index < len(list) {
return []string{list[index]}
}
return []string{""}
}
str := Trans(arg...)
index = (index+2)%(len(list)+2) - 2
if index == -1 {
list = append(str, list...)
} else if index == -2 {
list = append(list, str...)
} else {
if index < -2 {
index += len(list) + 2
}
if index < 0 {
index = 0
}
for i := len(list); i < index+len(str); i++ {
list = append(list, "")
}
for i := 0; i < len(str); i++ {
list[index+i] = str[i]
}
}
return list
}
func Elect(last interface{}, args ...interface{}) string {
if len(args) > 0 {
switch arg := args[0].(type) {
case []string:
index := 0
if len(args) > 1 {
switch a := args[1].(type) {
case string:
i, e := strconv.Atoi(a)
if e == nil {
index = i
}
case int:
index = a
}
}
if 0 <= index && index < len(arg) && arg[index] != "" {
return arg[index]
}
case string:
if arg != "" {
return arg
}
}
}
switch l := last.(type) {
case string:
return l
}
return ""
}
func Link(name string, url string) string {
return fmt.Sprintf("<a href=\"%s\" target=\"_blank\">%s</a>", url, name)
}
func FileName(name string, meta ...string) string {
result, app := strings.Split(name, "."), ""
if len(result) > 1 {
app, result = result[len(result)-1], result[:len(result)-1]
}
for _, v := range meta {
switch v {
case "year":
result = append(result, "_", time.Now().Format("2006"))
case "date":
result = append(result, "_", time.Now().Format("0102"))
case "time":
result = append(result, "_", time.Now().Format("2006_0102_1504"))
case "rand":
result = append(result, "_", Format(rand.Int()))
case "uniq":
result = append(result, "_", Format(Time()))
result = append(result, "_", Format(rand.Int()))
}
}
if app != "" {
result = append(result, ".", app)
}
return strings.Join(result, "")
}
func FmtSize(size uint64) string {
if size > 1<<30 {
return fmt.Sprintf("%d.%dG", size>>30, (size>>20)%1024*100/1024)
}
if size > 1<<20 {
return fmt.Sprintf("%d.%dM", size>>20, (size>>10)%1024*100/1024)
}
if size > 1<<10 {
return fmt.Sprintf("%d.%dK", size>>10, size%1024*100/1024)
}
return fmt.Sprintf("%dB", size)
}
func FmtNano(nano int64) string {
if nano > 1000000000 {
return fmt.Sprintf("%d.%ds", nano/1000000000, nano/100000000%100)
}
if nano > 1000000 {
return fmt.Sprintf("%d.%dms", nano/100000, nano/100000%100)
}
if nano > 1000 {
return fmt.Sprintf("%d.%dus", nano/1000, nano/100%100)
}
return fmt.Sprintf("%dns", nano)
}
func Block(root interface{}, args ...interface{}) interface{} {
return root
}
func Check(e error) bool {
if e != nil {
panic(e)
}
return true
}
func DirWalk(file string, hand func(file string)) {
s, e := os.Stat(file)
Check(e)
hand(file)
if s.IsDir() {
fs, e := ioutil.ReadDir(file)
Check(e)
for _, v := range fs {
DirWalk(path.Join(file, v.Name()), hand)
}
}
}

View File

@ -123,6 +123,8 @@ var page = Page({
page.onlayout() page.onlayout()
}) })
ctx.Search("layout") == "max" && (page.Conf("tree.display", "none"), page.Conf("menu.display", "none"))
ctx.Runs(page, form, function(msg) { ctx.Runs(page, form, function(msg) {
ui.menu.innerHTML = "", ui.text.innerHTML = msg.result? msg.result.join(""): "" ui.menu.innerHTML = "", ui.text.innerHTML = msg.result? msg.result.join(""): ""
kit.AppendChild(ui.menu, [{"tree": kit.OrderText(field, ui.text)}]) kit.AppendChild(ui.menu, [{"tree": kit.OrderText(field, ui.text)}])
@ -144,6 +146,10 @@ var page = Page({
case "tree": case "tree":
page.tree.Pane.Tree() page.tree.Pane.Tree()
break break
case "title":
ctx.Search("layout", ctx.Search("layout")? "": "max")
break
default: default:
page.confirm("logout?") && page.login.Pane.Exit() page.confirm("logout?") && page.login.Pane.Exit()
} }

View File

@ -1,11 +1,113 @@
## golang ## golang
- 官网: <https://golang.org/> - 官网: <https://golang.google.cn>
- 文档: <https://golang.org/doc/> - 下载: <https://golang.google.cn/dl>
- 文档: <https://golang.google.cn/doc/>
- 源码: <https://dl.google.com/go/go1.11.1.src.tar.gz> - 源码: <https://dl.google.com/go/go1.11.1.src.tar.gz>
- 开源: <https://github.com/golang> - 开源: <https://github.com/golang/go>
## 基本命令 bash tmux golang git vim
## 命令
```
env help version
run test install
get list
```
## 文件
```
package
import
const
type
func
var
```
## 语句
```
if else for range break continue
switch case default fallthrough
defer recover panic
goto return
go select
```
## 表达式
```
//
```
```
0 iota true false nil "" '' ``
int float
bool error
rune string
byte uintptr
interface struct
map chan
make len cap
append copy delete close
new complex real imag
```
## 官方包
```
os flag path time
io bufio
fmt
sync
math
bytes
image
unicode
strings
strconv
net
log
```
io fmt log net bufio bytes database
os flag time path errors syscall plugin
runtime context sync expvar testing debug reflect unsafe
math hash crypto sort container index
unicode strings strconv regexp
encoding archive compress
mime text html image
go/ast
go/build
go/constant
go/doc
go/format
go/importer
go/internal/gccgoimporter
go/internal/gcimporter
go/internal/srcimporter
go/parser
go/printer
go/scanner
go/token
go/types
internal/bytealg
internal/cpu
internal/nettrace
internal/poll
internal/race
internal/singleflight
internal/syscall/unix
internal/syscall/windows
internal/syscall/windows/registry
internal/syscall/windows/sysdll
internal/testenv
internal/testlog
internal/trace
``` ```
run clean build install run clean build install
fmt fix vet bug fmt fix vet bug
@ -13,6 +115,7 @@ mod get doc list
env help version env help version
test tool generate test tool generate
``` ```
## 编译过程 ## 编译过程
``` ```
main() // cmd/compile/main.go:40 main() // cmd/compile/main.go:40