Best Gauge code snippet using template.String
escape.go
Source:escape.go
...123 return e.escapeText(c, n)124 case *parse.WithNode:125 return e.escapeBranch(c, &n.BranchNode, "with")126 }127 panic("escaping " + n.String() + " is unimplemented")128}129// escapeAction escapes an action template node.130func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {131 if len(n.Pipe.Decl) != 0 {132 // A local variable assignment, not an interpolation.133 return c134 }135 c = nudge(c)136 s := make([]string, 0, 3)137 switch c.state {138 case stateError:139 return c140 case stateURL, stateCSSDqStr, stateCSSSqStr, stateCSSDqURL, stateCSSSqURL, stateCSSURL:141 switch c.urlPart {142 case urlPartNone:143 s = append(s, "html_template_urlfilter")144 fallthrough145 case urlPartPreQuery:146 switch c.state {147 case stateCSSDqStr, stateCSSSqStr:148 s = append(s, "html_template_cssescaper")149 default:150 s = append(s, "html_template_urlnormalizer")151 }152 case urlPartQueryOrFrag:153 s = append(s, "html_template_urlescaper")154 case urlPartUnknown:155 return context{156 state: stateError,157 err: errorf(ErrAmbigContext, n.Line, "%s appears in an ambiguous URL context", n),158 }159 default:160 panic(c.urlPart.String())161 }162 case stateJS:163 s = append(s, "html_template_jsvalescaper")164 // A slash after a value starts a div operator.165 c.jsCtx = jsCtxDivOp166 case stateJSDqStr, stateJSSqStr:167 s = append(s, "html_template_jsstrescaper")168 case stateJSRegexp:169 s = append(s, "html_template_jsregexpescaper")170 case stateCSS:171 s = append(s, "html_template_cssvaluefilter")172 case stateText:173 s = append(s, "html_template_htmlescaper")174 case stateRCDATA:175 s = append(s, "html_template_rcdataescaper")176 case stateAttr:177 // Handled below in delim check.178 case stateAttrName, stateTag:179 c.state = stateAttrName180 s = append(s, "html_template_htmlnamefilter")181 default:182 if isComment(c.state) {183 s = append(s, "html_template_commentescaper")184 } else {185 panic("unexpected state " + c.state.String())186 }187 }188 switch c.delim {189 case delimNone:190 // No extra-escaping needed for raw text content.191 case delimSpaceOrTagEnd:192 s = append(s, "html_template_nospaceescaper")193 default:194 s = append(s, "html_template_attrescaper")195 }196 e.editActionNode(n, s)197 return c198}199// ensurePipelineContains ensures that the pipeline has commands with200// the identifiers in s in order.201// If the pipeline already has some of the sanitizers, do not interfere.202// For example, if p is (.X | html) and s is ["escapeJSVal", "html"] then it203// has one matching, "html", and one to insert, "escapeJSVal", to produce204// (.X | escapeJSVal | html).205func ensurePipelineContains(p *parse.PipeNode, s []string) {206 if len(s) == 0 {207 return208 }209 n := len(p.Cmds)210 // Find the identifiers at the end of the command chain.211 idents := p.Cmds212 for i := n - 1; i >= 0; i-- {213 if cmd := p.Cmds[i]; len(cmd.Args) != 0 {214 if _, ok := cmd.Args[0].(*parse.IdentifierNode); ok {215 continue216 }217 }218 idents = p.Cmds[i+1:]219 }220 dups := 0221 for _, id := range idents {222 if escFnsEq(s[dups], (id.Args[0].(*parse.IdentifierNode)).Ident) {223 dups++224 if dups == len(s) {225 return226 }227 }228 }229 newCmds := make([]*parse.CommandNode, n-len(idents), n+len(s)-dups)230 copy(newCmds, p.Cmds)231 // Merge existing identifier commands with the sanitizers needed.232 for _, id := range idents {233 pos := id.Args[0].Position()234 i := indexOfStr((id.Args[0].(*parse.IdentifierNode)).Ident, s, escFnsEq)235 if i != -1 {236 for _, name := range s[:i] {237 newCmds = appendCmd(newCmds, newIdentCmd(name, pos))238 }239 s = s[i+1:]240 }241 newCmds = appendCmd(newCmds, id)242 }243 // Create any remaining sanitizers.244 for _, name := range s {245 newCmds = appendCmd(newCmds, newIdentCmd(name, p.Position()))246 }247 p.Cmds = newCmds248}249// redundantFuncs[a][b] implies that funcMap[b](funcMap[a](x)) == funcMap[a](x)250// for all x.251var redundantFuncs = map[string]map[string]bool{252 "html_template_commentescaper": {253 "html_template_attrescaper": true,254 "html_template_nospaceescaper": true,255 "html_template_htmlescaper": true,256 },257 "html_template_cssescaper": {258 "html_template_attrescaper": true,259 },260 "html_template_jsregexpescaper": {261 "html_template_attrescaper": true,262 },263 "html_template_jsstrescaper": {264 "html_template_attrescaper": true,265 },266 "html_template_urlescaper": {267 "html_template_urlnormalizer": true,268 },269}270// appendCmd appends the given command to the end of the command pipeline271// unless it is redundant with the last command.272func appendCmd(cmds []*parse.CommandNode, cmd *parse.CommandNode) []*parse.CommandNode {273 if n := len(cmds); n != 0 {274 last, ok := cmds[n-1].Args[0].(*parse.IdentifierNode)275 next, _ := cmd.Args[0].(*parse.IdentifierNode)276 if ok && redundantFuncs[last.Ident][next.Ident] {277 return cmds278 }279 }280 return append(cmds, cmd)281}282// indexOfStr is the first i such that eq(s, strs[i]) or -1 if s was not found.283func indexOfStr(s string, strs []string, eq func(a, b string) bool) int {284 for i, t := range strs {285 if eq(s, t) {286 return i287 }288 }289 return -1290}291// escFnsEq reports whether the two escaping functions are equivalent.292func escFnsEq(a, b string) bool {293 if e := equivEscapers[a]; e != "" {294 a = e295 }296 if e := equivEscapers[b]; e != "" {297 b = e298 }299 return a == b300}301// newIdentCmd produces a command containing a single identifier node.302func newIdentCmd(identifier string, pos parse.Pos) *parse.CommandNode {303 return &parse.CommandNode{304 NodeType: parse.NodeCommand,305 Args: []parse.Node{parse.NewIdentifier(identifier).SetPos(pos)},306 }307}308// nudge returns the context that would result from following empty string309// transitions from the input context.310// For example, parsing:311// `<a href=`312// will end in context{stateBeforeValue, attrURL}, but parsing one extra rune:313// `<a href=x`314// will end in context{stateURL, delimSpaceOrTagEnd, ...}.315// There are two transitions that happen when the 'x' is seen:316// (1) Transition from a before-value state to a start-of-value state without317// consuming any character.318// (2) Consume 'x' and transition past the first value character.319// In this case, nudging produces the context after (1) happens.320func nudge(c context) context {321 switch c.state {322 case stateTag:323 // In `<foo {{.}}`, the action should emit an attribute.324 c.state = stateAttrName325 case stateBeforeValue:326 // In `<foo bar={{.}}`, the action is an undelimited value.327 c.state, c.delim, c.attr = attrStartStates[c.attr], delimSpaceOrTagEnd, attrNone328 case stateAfterName:329 // In `<foo bar {{.}}`, the action is an attribute name.330 c.state, c.attr = stateAttrName, attrNone331 }332 return c333}334// join joins the two contexts of a branch template node. The result is an335// error context if either of the input contexts are error contexts, or if the336// the input contexts differ.337func join(a, b context, line int, nodeName string) context {338 if a.state == stateError {339 return a340 }341 if b.state == stateError {342 return b343 }344 if a.eq(b) {345 return a346 }347 c := a348 c.urlPart = b.urlPart349 if c.eq(b) {350 // The contexts differ only by urlPart.351 c.urlPart = urlPartUnknown352 return c353 }354 c = a355 c.jsCtx = b.jsCtx356 if c.eq(b) {357 // The contexts differ only by jsCtx.358 c.jsCtx = jsCtxUnknown359 return c360 }361 // Allow a nudged context to join with an unnudged one.362 // This means that363 // <p title={{if .C}}{{.}}{{end}}364 // ends in an unquoted value state even though the else branch365 // ends in stateBeforeValue.366 if c, d := nudge(a), nudge(b); !(c.eq(a) && d.eq(b)) {367 if e := join(c, d, line, nodeName); e.state != stateError {368 return e369 }370 }371 return context{372 state: stateError,373 err: errorf(ErrBranchEnd, line, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),374 }375}376// escapeBranch escapes a branch template node: "if", "range" and "with".377func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {378 c0 := e.escapeList(c, n.List)379 if nodeName == "range" && c0.state != stateError {380 // The "true" branch of a "range" node can execute multiple times.381 // We check that executing n.List once results in the same context382 // as executing n.List twice.383 c1, _ := e.escapeListConditionally(c0, n.List, nil)384 c0 = join(c0, c1, n.Line, nodeName)385 if c0.state == stateError {386 // Make clear that this is a problem on loop re-entry387 // since developers tend to overlook that branch when388 // debugging templates.389 c0.err.Line = n.Line390 c0.err.Description = "on range loop re-entry: " + c0.err.Description391 return c0392 }393 }394 c1 := e.escapeList(c, n.ElseList)395 return join(c0, c1, n.Line, nodeName)396}397// escapeList escapes a list template node.398func (e *escaper) escapeList(c context, n *parse.ListNode) context {399 if n == nil {400 return c401 }402 for _, m := range n.Nodes {403 c = e.escape(c, m)404 }405 return c406}407// escapeListConditionally escapes a list node but only preserves edits and408// inferences in e if the inferences and output context satisfy filter.409// It returns the best guess at an output context, and the result of the filter410// which is the same as whether e was updated.411func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {412 e1 := newEscaper(e.tmpl)413 // Make type inferences available to f.414 for k, v := range e.output {415 e1.output[k] = v416 }417 c = e1.escapeList(c, n)418 ok := filter != nil && filter(e1, c)419 if ok {420 // Copy inferences and edits from e1 back into e.421 for k, v := range e1.output {422 e.output[k] = v423 }424 for k, v := range e1.derived {425 e.derived[k] = v426 }427 for k, v := range e1.called {428 e.called[k] = v429 }430 for k, v := range e1.actionNodeEdits {431 e.editActionNode(k, v)432 }433 for k, v := range e1.templateNodeEdits {434 e.editTemplateNode(k, v)435 }436 for k, v := range e1.textNodeEdits {437 e.editTextNode(k, v)438 }439 }440 return c, ok441}442// escapeTemplate escapes a {{template}} call node.443func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {444 c, name := e.escapeTree(c, n.Name, n.Line)445 if name != n.Name {446 e.editTemplateNode(n, name)447 }448 return c449}450// escapeTree escapes the named template starting in the given context as451// necessary and returns its output context.452func (e *escaper) escapeTree(c context, name string, line int) (context, string) {453 // Mangle the template name with the input context to produce a reliable454 // identifier.455 dname := c.mangle(name)456 e.called[dname] = true457 if out, ok := e.output[dname]; ok {458 // Already escaped.459 return out, dname460 }461 t := e.template(name)462 if t == nil {463 // Two cases: The template exists but is empty, or has never been mentioned at464 // all. Distinguish the cases in the error messages.465 if e.tmpl.set[name] != nil {466 return context{467 state: stateError,468 err: errorf(ErrNoSuchTemplate, line, "%q is an incomplete or empty template", name),469 }, dname470 }471 return context{472 state: stateError,473 err: errorf(ErrNoSuchTemplate, line, "no such template %q", name),474 }, dname475 }476 if dname != name {477 // Use any template derived during an earlier call to escapeTemplate478 // with different top level templates, or clone if necessary.479 dt := e.template(dname)480 if dt == nil {481 dt = template.New(dname)482 dt.Tree = &parse.Tree{Name: dname, Root: t.Root.CopyList()}483 e.derived[dname] = dt484 }485 t = dt486 }487 return e.computeOutCtx(c, t), dname488}489// computeOutCtx takes a template and its start context and computes the output490// context while storing any inferences in e.491func (e *escaper) computeOutCtx(c context, t *template.Template) context {492 // Propagate context over the body.493 c1, ok := e.escapeTemplateBody(c, t)494 if !ok {495 // Look for a fixed point by assuming c1 as the output context.496 if c2, ok2 := e.escapeTemplateBody(c1, t); ok2 {497 c1, ok = c2, true498 }499 // Use c1 as the error context if neither assumption worked.500 }501 if !ok && c1.state != stateError {502 return context{503 state: stateError,504 // TODO: Find the first node with a line in t.text.Tree.Root505 err: errorf(ErrOutputContext, 0, "cannot compute output context for template %s", t.Name()),506 }507 }508 return c1509}510// escapeTemplateBody escapes the given template assuming the given output511// context, and returns the best guess at the output context and whether the512// assumption was correct.513func (e *escaper) escapeTemplateBody(c context, t *template.Template) (context, bool) {514 filter := func(e1 *escaper, c1 context) bool {515 if c1.state == stateError {516 // Do not update the input escaper, e.517 return false518 }519 if !e1.called[t.Name()] {520 // If t is not recursively called, then c1 is an521 // accurate output context.522 return true523 }524 // c1 is accurate if it matches our assumed output context.525 return c.eq(c1)526 }527 // We need to assume an output context so that recursive template calls528 // take the fast path out of escapeTree instead of infinitely recursing.529 // Naively assuming that the input context is the same as the output530 // works >90% of the time.531 e.output[t.Name()] = c532 return e.escapeListConditionally(c, t.Tree.Root, filter)533}534// delimEnds maps each delim to a string of characters that terminate it.535var delimEnds = [...]string{536 delimDoubleQuote: `"`,537 delimSingleQuote: "'",538 // Determined empirically by running the below in various browsers.539 // var div = document.createElement("DIV");540 // for (var i = 0; i < 0x10000; ++i) {541 // div.innerHTML = "<span title=x" + String.fromCharCode(i) + "-bar>";542 // if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0)543 // document.write("<p>U+" + i.toString(16));544 // }545 delimSpaceOrTagEnd: " \t\n\f\r>",546}547var doctypeBytes = []byte("<!DOCTYPE")548// escapeText escapes a text template node.549func (e *escaper) escapeText(c context, n *parse.TextNode) context {550 s, written, i, b := n.Text, 0, 0, new(bytes.Buffer)551 for i != len(s) {552 c1, nread := contextAfterText(c, s[i:])553 i1 := i + nread554 if c.state == stateText || c.state == stateRCDATA {555 end := i1556 if c1.state != c.state {557 for j := end - 1; j >= i; j-- {558 if s[j] == '<' {559 end = j560 break561 }562 }563 }564 for j := i; j < end; j++ {565 if s[j] == '<' && !bytes.HasPrefix(bytes.ToUpper(s[j:]), doctypeBytes) {566 b.Write(s[written:j])567 b.WriteString("<")568 written = j + 1569 }570 }571 } else if isComment(c.state) && c.delim == delimNone {572 switch c.state {573 case stateJSBlockCmt:574 // http://es5.github.com/#x7.4:575 // "Comments behave like white space and are576 // discarded except that, if a MultiLineComment577 // contains a line terminator character, then578 // the entire comment is considered to be a579 // LineTerminator for purposes of parsing by580 // the syntactic grammar."581 if bytes.IndexAny(s[written:i1], "\n\r\u2028\u2029") != -1 {582 b.WriteByte('\n')583 } else {584 b.WriteByte(' ')585 }586 case stateCSSBlockCmt:587 b.WriteByte(' ')588 }589 written = i1590 }591 if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {592 // Preserve the portion between written and the comment start.593 cs := i1 - 2594 if c1.state == stateHTMLCmt {595 // "<!--" instead of "/*" or "//"596 cs -= 2597 }598 b.Write(s[written:cs])599 written = i1600 }601 if i == i1 && c.state == c1.state {602 panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))603 }604 c, i = c1, i1605 }606 if written != 0 && c.state != stateError {607 if !isComment(c.state) || c.delim != delimNone {608 b.Write(n.Text[written:])609 }610 e.editTextNode(n, b.Bytes())611 }612 return c613}614// contextAfterText starts in context c, consumes some tokens from the front of615// s, then returns the context after those tokens and the unprocessed suffix.616func contextAfterText(c context, s []byte) (context, int) {617 if c.delim == delimNone {618 c1, i := tSpecialTagEnd(c, s)619 if i == 0 {620 // A special end tag (`</script>`) has been seen and621 // all content preceding it has been consumed.622 return c1, 0623 }624 // Consider all content up to any end tag.625 return transitionFunc[c.state](c, s[:i])626 }627 i := bytes.IndexAny(s, delimEnds[c.delim])628 if i == -1 {629 i = len(s)630 }631 if c.delim == delimSpaceOrTagEnd {632 // http://www.w3.org/TR/html5/tokenization.html#attribute-value-unquoted-state633 // lists the runes below as error characters.634 // Error out because HTML parsers may differ on whether635 // "<a id= onclick=f(" ends inside id's or onclick's value,636 // "<a class=`foo " ends inside a value,637 // "<a style=font:'Arial'" needs open-quote fixup.638 // IE treats '`' as a quotation character.639 if j := bytes.IndexAny(s[:i], "\"'<=`"); j >= 0 {640 return context{641 state: stateError,642 err: errorf(ErrBadHTML, 0, "%q in unquoted attr: %q", s[j:j+1], s[:i]),643 }, len(s)644 }645 }646 if i == len(s) {647 // Remain inside the attribute.648 // Decode the value so non-HTML rules can easily handle649 // <button onclick="alert("Hi!")">650 // without having to entity decode token boundaries.651 for u := []byte(html.UnescapeString(string(s))); len(u) != 0; {652 c1, i1 := transitionFunc[c.state](c, u)653 c, u = c1, u[i1:]654 }655 return c, len(s)656 }657 if c.delim != delimSpaceOrTagEnd {658 // Consume any quote.659 i++660 }661 // On exiting an attribute, we discard all state information662 // except the state and element.663 return context{state: stateTag, element: c.element}, i664}665// editActionNode records a change to an action pipeline for later commit.666func (e *escaper) editActionNode(n *parse.ActionNode, cmds []string) {667 if _, ok := e.actionNodeEdits[n]; ok {668 panic(fmt.Sprintf("node %s shared between templates", n))669 }670 e.actionNodeEdits[n] = cmds671}672// editTemplateNode records a change to a {{template}} callee for later commit.673func (e *escaper) editTemplateNode(n *parse.TemplateNode, callee string) {674 if _, ok := e.templateNodeEdits[n]; ok {675 panic(fmt.Sprintf("node %s shared between templates", n))676 }677 e.templateNodeEdits[n] = callee678}679// editTextNode records a change to a text node for later commit.680func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {681 if _, ok := e.textNodeEdits[n]; ok {682 panic(fmt.Sprintf("node %s shared between templates", n))683 }684 e.textNodeEdits[n] = text685}686// commit applies changes to actions and template calls needed to contextually687// autoescape content and adds any derived templates to the set.688func (e *escaper) commit() {689 for name := range e.output {690 e.template(name).Funcs(funcMap)691 }692 for _, t := range e.derived {693 if _, err := e.tmpl.text.AddParseTree(t.Name(), t.Tree); err != nil {694 panic("error adding derived template")695 }696 }697 for n, s := range e.actionNodeEdits {698 ensurePipelineContains(n.Pipe, s)699 }700 for n, name := range e.templateNodeEdits {701 n.Name = name702 }703 for n, s := range e.textNodeEdits {704 n.Text = s705 }706}707// template returns the named template given a mangled template name.708func (e *escaper) template(name string) *template.Template {709 t := e.tmpl.text.Lookup(name)710 if t == nil {711 t = e.derived[name]712 }713 return t714}715// Forwarding functions so that clients need only import this package716// to reach the general escaping functions of text/template.717// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.718func HTMLEscape(w io.Writer, b []byte) {719 template.HTMLEscape(w, b)720}721// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.722func HTMLEscapeString(s string) string {723 return template.HTMLEscapeString(s)724}725// HTMLEscaper returns the escaped HTML equivalent of the textual726// representation of its arguments.727func HTMLEscaper(args ...interface{}) string {728 return template.HTMLEscaper(args...)729}730// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.731func JSEscape(w io.Writer, b []byte) {732 template.JSEscape(w, b)733}734// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.735func JSEscapeString(s string) string {736 return template.JSEscapeString(s)737}738// JSEscaper returns the escaped JavaScript equivalent of the textual739// representation of its arguments.740func JSEscaper(args ...interface{}) string {741 return template.JSEscaper(args...)742}743// URLQueryEscaper returns the escaped value of the textual representation of744// its arguments in a form suitable for embedding in a URL query.745func URLQueryEscaper(args ...interface{}) string {746 return template.URLQueryEscaper(args...)747}...
log.go
Source:log.go
1/**********************************************************************2* @Author: Eiger (201820114847@mail.scut.edu.cn)3* @Date: 10/19/20 9:10 AM4* @Description: The file is for5***********************************************************************/6package log7import (8 "fmt"9)10// Logger åºäºsugarLoggerå
è£
11type Logger struct {12 module string13 id string14 prefix string15}16// NewLogger æ°å»º17func NewLogger(module string, id string) *Logger {18 if loggers[id] == nil {19 panic("init global zap logger first")20 }21 prefix := fmt.Sprintf("\t[%s](%s)\t", module, id)22 return &Logger{23 module: module,24 id: id,25 prefix: prefix,26 }27}28func (logger *Logger) Debug(args ...interface{}) {29 args = append([]interface{}{logger.prefix}, args...)30 loggers[logger.id].Debug(args...)31}32func (logger *Logger) Debugf(template string, args ...interface{}) {33 template = fmt.Sprintf("%s%s", logger.prefix, template)34 loggers[logger.id].Debugf(template, args...)35}36func (logger *Logger) Debugw(msg string, keysAndValues ...interface{}) {37 msg = fmt.Sprintf("%s%s", logger.prefix, msg)38 loggers[logger.id].Debugw(msg, keysAndValues...)39}40func (logger *Logger) Info(args ...interface{}) {41 args = append([]interface{}{logger.prefix}, args...)42 loggers[logger.id].Info(args...)43}44func (logger *Logger) Infof(template string, args ...interface{}) {45 template = fmt.Sprintf("%s%s", logger.prefix, template)46 loggers[logger.id].Infof(template, args...)47}48func (logger *Logger) Infow(msg string, keysAndValues ...interface{}) {49 msg = fmt.Sprintf("%s%s", logger.prefix, msg)50 loggers[logger.id].Infow(msg, keysAndValues...)51}52func (logger *Logger) Warn(args ...interface{}) {53 args = append([]interface{}{logger.prefix}, args...)54 loggers[logger.id].Warn(args...)55}56func (logger *Logger) Warnf(template string, args ...interface{}) {57 template = fmt.Sprintf("%s%s", logger.prefix, template)58 loggers[logger.id].Warnf(template, args...)59}60func (logger *Logger) Warnw(msg string, keysAndValues ...interface{}) {61 msg = fmt.Sprintf("%s%s", logger.prefix, msg)62 loggers[logger.id].Warnw(msg, keysAndValues...)63}64func (logger *Logger) Error(args ...interface{}) {65 args = append([]interface{}{logger.prefix}, args...)66 loggers[logger.id].Error(args...)67}68func (logger *Logger) Errorf(template string, args ...interface{}) {69 template = fmt.Sprintf("%s%s", logger.prefix, template)70 loggers[logger.id].Errorf(template, args...)71}72func (logger *Logger) Errorw(msg string, keysAndValues ...interface{}) {73 msg = fmt.Sprintf("%s%s", logger.prefix, msg)74 loggers[logger.id].Errorw(msg, keysAndValues...)75}76func (logger *Logger) Panic(args ...interface{}) {77 args = append([]interface{}{logger.prefix}, args...)78 loggers[logger.id].Panic(args...)79}80func (logger *Logger) Panicf(template string, args ...interface{}) {81 template = fmt.Sprintf("%s%s", logger.prefix, template)82 loggers[logger.id].Panicf(template, args...)83}84func (logger *Logger) Panicw(msg string, keysAndValues ...interface{}) {85 msg = fmt.Sprintf("%s%s", logger.prefix, msg)86 loggers[logger.id].Panicw(msg, keysAndValues...)87}88func (logger *Logger) Fatal(args ...interface{}) {89 args = append([]interface{}{logger.prefix}, args...)90 loggers[logger.id].Fatal(args...)91}92func (logger *Logger) Fatalf(template string, args ...interface{}) {93 template = fmt.Sprintf("%s%s", logger.prefix, template)94 loggers[logger.id].Fatalf(template, args...)95}96func (logger *Logger) Fatalw(msg string, keysAndValues ...interface{}) {97 msg = fmt.Sprintf("%s%s", logger.prefix, msg)98 loggers[logger.id].Fatalw(msg, keysAndValues...)99}100//101//// Log ææ¥å¿102//func (logger *Logger) Log(v ...interface{}) {103// logger.logger.Println("[L-O-G] ", v)104//}105//106//// Logf ææ¥å¿107//func (logger *Logger) Logf(format string, v ...interface{}) {108// format = fmt.Sprintf("[L-O-G] %s", format)109// logger.logger.Printf(format, v...)110//}111//112//// Error æ¥é113//func (logger *Logger) Error(v ...interface{}) {114// logger.logger.Println("[ERROR] ", v)115//}116//117//// Errorf æ¥é118//func (logger *Logger) Errorf(format string, v ...interface{}) {119// format = fmt.Sprintf("[ERROR] %s", format)120// logger.logger.Printf(format, v...)121//}122//123//// Fatal è´å½é误124//func (logger *Logger) Fatal(v ...interface{}) {125// logger.logger.Fatalln("[FATAL] ", v)126//}127//128//// Fatalf è´å½é误129//func (logger *Logger) Fatalf(format string, v ...interface{}) {130// format = fmt.Sprintf("[FATAL] %s", format)131// logger.logger.Fatalf(format, v...)132//}133//134//// Panic ææ
135//func (logger *Logger) Panic(v ...interface{}) {136// logger.logger.Panicln("[PANIC] ", v)137//}138//139//// Panicf ææ
140//func (logger *Logger) Panicf(format string, v ...interface{}) {141// format = fmt.Sprintf("[PANIC] %s", format)142// logger.logger.Panicf(format, v...)143//}...
generate.go
Source:generate.go
1// +build ignore2//generate command: go run gen/generate.go --html views/*.html --tmpl=views/setting.tmpl --output=setting --package=setting3package main4import (5 "fmt"6 "io/ioutil"7 "log"8 "os"9 "path/filepath"10 "strings"11 "github.com/jessevdk/go-flags"12)13//var -14var (15 KEYWORD = "$$HTML$$"16 NAME = "$$NAME$$"17 ID = "$$ID$$"18 PACKAGE = "$$PACKAGE$$"19 TMPLS = "$$TMPLS$$"20)21//options - parameter22type options struct {23 Input string `long:"html" description:"html file"`24 Output string `long:"output" description:"output go file"`25 Tmpl string `long:"tmpl" description:"template file"`26 Pkg string `long:"package" description:"go package name"`27}28func main() {29 var opts options30 if _, err := flags.Parse(&opts); err != nil {31 os.Exit(-1)32 }33 if opts.Pkg == "" {34 opts.Pkg = "main"35 }36 //read template37 var tmplsrc string = generateTemplate38 if opts.Tmpl != "" {39 t, err := ioutil.ReadFile(opts.Tmpl)40 if err != nil {41 log.Printf("Cannot open %q: %v\n", opts.Tmpl, err)42 os.Exit(-1)43 }44 tmplsrc = string(t)45 }46 tmplsrc = strings.ReplaceAll(tmplsrc, `\x60`, "`")47 var summary string48 var dir string49 if !strings.HasSuffix(opts.Output, ".go") {50 dir = opts.Output51 summary = filepath.Join(dir, "template.go")52 } else {53 //check output directory54 dir = filepath.Dir(opts.Output)55 if !Exists(dir) {56 err := os.MkdirAll(dir, 0755)57 if err != nil {58 log.Println("Failed to create output directory", err)59 os.Exit(-1)60 }61 }62 summary = filepath.Join(dir, "template.go")63 }64 filenames := make([]string, 0)65 //glob66 if strings.Index(opts.Input, "*") > -1 || strings.Index(opts.Input, "?") > -1 {67 names, err := filepath.Glob(opts.Input)68 if err != nil {69 log.Printf("Cannot find input file. %v", err)70 os.Exit(-1)71 }72 if len(names) == 0 {73 log.Printf("template: pattern matches no files: %#q", opts.Input)74 os.Exit(-1)75 }76 filenames = append(filenames, names...)77 } else {78 filenames = append(filenames, opts.Input)79 }80 tmpls := ""81 for _, filename := range filenames {82 //read html83 b, err := ioutil.ReadFile(filename)84 if err != nil {85 log.Printf("Cannot open %q: %v\n", filename, err)86 os.Exit(-1)87 }88 tmpl := tmplsrc89 //Package90 tmpl = strings.ReplaceAll(tmpl, PACKAGE, opts.Pkg)91 base := Name(filename)92 title := Title(base)93 tmpl = strings.ReplaceAll(tmpl, ID, title)94 //define templates95 dtName := title + "Name"96 dtTmpl := title + "Template"97 tmpls = tmpls + defineTmpl(dtName, dtTmpl)98 //Name99 name := filepath.Base(filename)100 tmpl = strings.ReplaceAll(tmpl, NAME, name)101 //html body102 tmpl = strings.ReplaceAll(tmpl, KEYWORD, string(b))103 gofile := base + ".go"104 output := filepath.Join(dir, gofile)105 //write to go file106 err = ioutil.WriteFile(output, []byte(tmpl), 0644)107 if err != nil {108 log.Printf("Cannot write %v: %v\n", output, err)109 os.Exit(-1)110 }111 }112 if len(tmpls) > 0 {113 tmpl := generateSummary114 //Package115 tmpl = strings.ReplaceAll(tmpl, PACKAGE, opts.Pkg)116 //define templates117 tmpl = strings.ReplaceAll(tmpl, TMPLS, tmpls)118 err := ioutil.WriteFile(summary, []byte(tmpl), 0644)119 if err != nil {120 log.Printf("Cannot write %v: %v\n", summary, err)121 os.Exit(-1)122 }123 }124}125//Exists -126func Exists(name string) bool {127 _, err := os.Stat(name)128 return !os.IsNotExist(err)129}130//Name -131func Name(name string) string {132 fileName := filepath.Base(name)133 return fileName[:len(fileName)-len(filepath.Ext(fileName))]134}135//Title -136func Title(name string) string {137 return strings.Title(strings.ToLower(name))138}139var generateTemplate = `140// Code generated .* DO NOT EDIT\.$141package $$PACKAGE$$142//Name - page Name143var $$ID$$Name string = \x60$$NAME$$\x60144//Template - page template145var $$ID$$Template string = \x60$$HTML$$\x60146`147func defineTmpl(name, data string) string {148 return fmt.Sprintf("{Name: %s, Data: %s},", name, data)149}150var generateSummary = `// Code generated .* DO NOT EDIT\.$151package $$PACKAGE$$152import (153 "text/template"154)155//DefineTemplate -156type DefineTemplate struct {157 Name string158 Data string159}160//NewTemplate - page template161func NewTemplate() (*template.Template, error) {162 tmpls := []DefineTemplate{163 $$TMPLS$$164 }165 var t *template.Template166 var w *template.Template167 for _, d := range tmpls {168 if t == nil {169 t = template.New(d.Name)170 }171 if d.Name == t.Name() {172 w = t173 } else {174 w = t.New(d.Name)175 }176 _, err := w.Parse(d.Data)177 if err != nil {178 return nil, err179 }180 }181 return t, nil182}183`...
String
Using AI Code Generation
1import (2func main() {3 t := template.New("test")4 t, _ = t.Parse("{{.Name}}'s salary is {{.Salary}}")5 p := Person{"John", 1000}6 t.Execute(os.Stdout, p)7}8type Person struct {9}10import (11func main() {12 t := template.New("test")13 t, _ = t.Parse("{{.Name}}'s salary is {{.Salary}}")14 p := Person{"John", 1000}15 t.Execute(os.Stdout, p)16}17type Person struct {18}19func (p Person) String() string {20 return fmt.Sprintf("Name: %s, Salary: %d", p.Name, p.Salary)21}
String
Using AI Code Generation
1import "fmt"2import "text/template"3func main() {4 t, _ := template.New("foo").Parse("{{.}}")5 t.Execute(os.Stdout, "Hello, playground")6}7import "fmt"8import "text/template"9func main() {10 t, _ := template.New("foo").Parse("{{.}}")11 t.Execute(os.Stdout, "Hello, playground")12}13import "fmt"14import "text/template"15func main() {16 t, _ := template.New("foo").Parse("{{.}}")17 t.Execute(os.Stdout, "Hello, playground")18}19import "fmt"20import "text/template"21func main() {22 t, _ := template.New("foo").Parse("{{.}}")23 t.Execute(os.Stdout, "Hello, playground")24}25import "fmt"26import "text/template"27func main() {28 t, _ := template.New("foo").Parse("{{.}}")29 t.Execute(os.Stdout, "Hello, playground")30}31import "fmt"32import "text/template"33func main() {34 t, _ := template.New("foo").Parse("{{.}}")35 t.Execute(os.Stdout, "Hello, playground")36}37import "fmt"38import "text/template"39func main() {40 t, _ := template.New("foo").Parse("{{.}}")41 t.Execute(os.Stdout, "Hello, playground")42}43import "fmt"44import "text/template"45func main() {46 t, _ := template.New("foo").Parse("{{.}}")47 t.Execute(os.Stdout, "Hello, playground")48}49import "fmt"50import "text
String
Using AI Code Generation
1import "fmt"2import "text/template"3func main() {4 t1 := template.New("t1")5 t1, _ = t1.Parse("{{.}}")6 t1.Execute(os.Stdout, "Hello World")7}8import "fmt"9import "text/template"10func main() {11 t1 := template.New("t1")12 t1, _ = t1.Parse("{{.}}")13 fmt.Println(t1.String())14}15{{.}}16import "fmt"17import "text/template"18func main() {19 t1 := template.New("t1")20 t1, _ = t1.Parse("{{.}}")21 t2 := t1.Lookup("t1")22 t2.Execute(os.Stdout, "Hello World")23}24import "fmt"25import "text/template"26func main() {27 t1 := template.New("t1")28 t1, _ = t1.Parse("{{.}}")29 t2 := template.New("t2")30 t2, _ = t2.Parse("{{.}}")31 t1.AddParseTree("t2", t2.Tree)32 t1.ExecuteTemplate(os.Stdout, "t2", "Hello World")33}34import "fmt"35import "text/template"36func main() {37 t1 := template.New("t1")38 t1, _ = t1.Parse("{{.}}")39 t2 := template.New("t2")40 t2, _ = t2.Parse("{{.}}")41 t1.AddParseTree("t2", t2.Tree)42 t1.ExecuteTemplate(os.Stdout, "t2", "Hello World")43}
String
Using AI Code Generation
1import (2func main() {3 t := template.New("Hello")4 t, _ = t.Parse("Hello {{.}}!")5 t.Execute(os.Stdout, "World")6}
String
Using AI Code Generation
1import "fmt"2import "text/template"3func main() {4 t := template.New("foo")5 t = template.Must(t.Parse("{{.Name}} {{.Age}}"))6 err := t.Execute(os.Stdout, Person{"Alice", 20})7 if err != nil {8 fmt.Println("error:", err)9 }10}11import "fmt"12import "text/template"13func main() {14 t := template.New("foo")15 t = template.Must(t.Parse("{{.Name}} {{.Age}}"))16 err := t.Execute(os.Stdout, Person{"Alice", 20})17 if err != nil {18 fmt.Println("error:", err)19 }20}21import "fmt"22import "text/template"23func main() {24 t := template.New("foo")25 t = template.Must(t.Parse("{{.Name}} {{.Age}}"))26 err := t.Execute(os.Stdout, Person{"Alice", 20})27 if err != nil {28 fmt.Println("error:", err)29 }30}
String
Using AI Code Generation
1import (2func main() {3 t := template.Must(template.New("hello").Parse(s))4 err := t.Execute(os.Stdout, nil)5 if err != nil {6 fmt.Println("Error: ", err)7 }8}9import (10func (s String) print() {11 fmt.Println(s)12}13func main() {14 s.print()15}16import (17func (s String) print() {18 fmt.Println(s)19}20func main() {21 s.print()22}23import (24func (s String) print() {25 fmt.Println(s)26}27func main() {
String
Using AI Code Generation
1import (2func main() {3 t := template.New("test")4 t, _ = t.Parse("Hello {{.}}!")5 t.Execute(os.Stdout, "World")6}
String
Using AI Code Generation
1import (2type Person struct {3}4func main() {5 p := Person{"Sourav", 23}6 t := template.New("Person template")7 t, _ = t.Parse("Name: {{.Name}} Age: {{.Age}}")8 t.Execute(os.Stdout, p)9}10import (11type Person struct {12}13func main() {14 p := []Person{15 {"Sourav", 23},16 {"Sourav", 23},17 {"Sourav", 23},18 {"Sourav", 23},19 }20 t := template.New("Person template")21 t, _ = t.Parse("Name: {{.Name}} Age: {{.Age}}")22 t.Execute(os.Stdout, p)23}24import (25type Person struct {26}27func main() {28 p := []Person{29 {"Sourav", 23},30 {"Sourav", 23},31 {"Sourav", 23},32 {"Sourav", 23},33 }34 t := template.New("Person template")35 t, _ = t.Parse("{{range .}}Name: {{.Name}} Age: {{.Age}}{{end}}")36 t.Execute(os.Stdout, p)37}
String
Using AI Code Generation
1import (2func main() {3 var str = "Hello {{.}}"4 var tmpl = template.Must(template.New("test").Parse(str))5 tmpl.Execute(&builder, "World")6 fmt.Println(builder.String())7}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!