Commit ff18ae25 authored by 傅小黑's avatar 傅小黑

add api comments in file memzipfile.go,reload.go,router.go,template.go and…

add api comments in file memzipfile.go,reload.go,router.go,template.go and templatefunc.go, fix spelling error GetInitListner as GetInitListener.
parent 57781d10
...@@ -61,7 +61,7 @@ func (app *App) Run() { ...@@ -61,7 +61,7 @@ func (app *App) Run() {
if nil != err { if nil != err {
BeeLogger.Critical("ResolveTCPAddr:", err) BeeLogger.Critical("ResolveTCPAddr:", err)
} }
l, err = GetInitListner(laddr) l, err = GetInitListener(laddr)
theStoppable = newStoppable(l) theStoppable = newStoppable(l)
err = server.Serve(theStoppable) err = server.Serve(theStoppable)
theStoppable.wg.Wait() theStoppable.wg.Wait()
...@@ -92,19 +92,19 @@ func (app *App) Run() { ...@@ -92,19 +92,19 @@ func (app *App) Run() {
// The c argument needs a controller handler implemented beego.ControllerInterface. // The c argument needs a controller handler implemented beego.ControllerInterface.
// The mapping methods argument only need one string to define custom router rules. // The mapping methods argument only need one string to define custom router rules.
// usage: // usage:
// simple router // simple router
// beego.Router("/admin", &admin.UserController{}) // beego.Router("/admin", &admin.UserController{})
// beego.Router("/admin/index", &admin.ArticleController{}) // beego.Router("/admin/index", &admin.ArticleController{})
// //
// regex router // regex router
// //
// beego.Router(“/api/:id([0-9]+)“, &controllers.RController{}) // beego.Router(“/api/:id([0-9]+)“, &controllers.RController{})
// //
// custom rules // custom rules
// beego.Router("/api/list",&RestController{},"*:ListFood") // beego.Router("/api/list",&RestController{},"*:ListFood")
// beego.Router("/api/create",&RestController{},"post:CreateFood") // beego.Router("/api/create",&RestController{},"post:CreateFood")
// beego.Router("/api/update",&RestController{},"put:UpdateFood") // beego.Router("/api/update",&RestController{},"put:UpdateFood")
// beego.Router("/api/delete",&RestController{},"delete:DeleteFood") // beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App { func (app *App) Router(path string, c ControllerInterface, mappingMethods ...string) *App {
app.Handlers.Add(path, c, mappingMethods...) app.Handlers.Add(path, c, mappingMethods...)
return app return app
...@@ -118,7 +118,7 @@ func (app *App) AutoRouter(c ControllerInterface) *App { ...@@ -118,7 +118,7 @@ func (app *App) AutoRouter(c ControllerInterface) *App {
return app return app
} }
// UrlFor does another controller handler with params in current context. // UrlFor creates a url with another registered controller handler with params.
// The endpoint is formed as path.controller.name to defined the controller method which will run. // The endpoint is formed as path.controller.name to defined the controller method which will run.
// The values need key-pair data to assign into controller method. // The values need key-pair data to assign into controller method.
func (app *App) UrlFor(endpoint string, values ...string) string { func (app *App) UrlFor(endpoint string, values ...string) string {
......
...@@ -16,7 +16,8 @@ import ( ...@@ -16,7 +16,8 @@ import (
var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo) var gmfim map[string]*MemFileInfo = make(map[string]*MemFileInfo)
//TODO: 加锁保证数据完整性 // OpenMemZipFile returns MemFile object with a compressed static file.
// it's used for serve static file if gzip enable.
func OpenMemZipFile(path string, zip string) (*MemFile, error) { func OpenMemZipFile(path string, zip string) (*MemFile, error) {
osfile, e := os.Open(path) osfile, e := os.Open(path)
if e != nil { if e != nil {
...@@ -86,6 +87,8 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) { ...@@ -86,6 +87,8 @@ func OpenMemZipFile(path string, zip string) (*MemFile, error) {
return &MemFile{fi: cfi, offset: 0}, nil return &MemFile{fi: cfi, offset: 0}, nil
} }
// MemFileInfo contains a compressed file bytes and file information.
// it implements os.FileInfo interface.
type MemFileInfo struct { type MemFileInfo struct {
os.FileInfo os.FileInfo
modTime time.Time modTime time.Time
...@@ -94,49 +97,62 @@ type MemFileInfo struct { ...@@ -94,49 +97,62 @@ type MemFileInfo struct {
fileSize int64 fileSize int64
} }
// Name returns the compressed filename.
func (fi *MemFileInfo) Name() string { func (fi *MemFileInfo) Name() string {
return fi.Name() return fi.Name()
} }
// Size returns the raw file content size, not compressed size.
func (fi *MemFileInfo) Size() int64 { func (fi *MemFileInfo) Size() int64 {
return fi.contentSize return fi.contentSize
} }
// Mode returns file mode.
func (fi *MemFileInfo) Mode() os.FileMode { func (fi *MemFileInfo) Mode() os.FileMode {
return fi.Mode() return fi.Mode()
} }
// ModTime returns the last modified time of raw file.
func (fi *MemFileInfo) ModTime() time.Time { func (fi *MemFileInfo) ModTime() time.Time {
return fi.modTime return fi.modTime
} }
// IsDir returns the compressing file is a directory or not.
func (fi *MemFileInfo) IsDir() bool { func (fi *MemFileInfo) IsDir() bool {
return fi.IsDir() return fi.IsDir()
} }
// return nil. implement the os.FileInfo interface method.
func (fi *MemFileInfo) Sys() interface{} { func (fi *MemFileInfo) Sys() interface{} {
return nil return nil
} }
// MemFile contains MemFileInfo and bytes offset when reading.
// it implements io.Reader,io.ReadCloser and io.Seeker.
type MemFile struct { type MemFile struct {
fi *MemFileInfo fi *MemFileInfo
offset int64 offset int64
} }
// Close memfile.
func (f *MemFile) Close() error { func (f *MemFile) Close() error {
return nil return nil
} }
// Get os.FileInfo of memfile.
func (f *MemFile) Stat() (os.FileInfo, error) { func (f *MemFile) Stat() (os.FileInfo, error) {
return f.fi, nil return f.fi, nil
} }
// read os.FileInfo of files in directory of memfile.
// it returns empty slice.
func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) { func (f *MemFile) Readdir(count int) ([]os.FileInfo, error) {
infos := []os.FileInfo{} infos := []os.FileInfo{}
return infos, nil return infos, nil
} }
// Read bytes from the compressed file bytes.
func (f *MemFile) Read(p []byte) (n int, err error) { func (f *MemFile) Read(p []byte) (n int, err error) {
if len(f.fi.content)-int(f.offset) >= len(p) { if len(f.fi.content)-int(f.offset) >= len(p) {
n = len(p) n = len(p)
...@@ -152,6 +168,7 @@ func (f *MemFile) Read(p []byte) (n int, err error) { ...@@ -152,6 +168,7 @@ func (f *MemFile) Read(p []byte) (n int, err error) {
var errWhence = errors.New("Seek: invalid whence") var errWhence = errors.New("Seek: invalid whence")
var errOffset = errors.New("Seek: invalid offset") var errOffset = errors.New("Seek: invalid offset")
// Read bytes from the compressed file bytes by seeker.
func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) { func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
switch whence { switch whence {
default: default:
...@@ -169,8 +186,9 @@ func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) { ...@@ -169,8 +186,9 @@ func (f *MemFile) Seek(offset int64, whence int) (ret int64, err error) {
return f.offset, nil return f.offset, nil
} }
//返回: gzip, deflate, 优先gzip // GetAcceptEncodingZip returns accept encoding format in http header.
//返回空, 表示不zip // zip is first, then deflate if both accepted.
// If no accepted, return empty string.
func GetAcceptEncodingZip(r *http.Request) string { func GetAcceptEncodingZip(r *http.Request) string {
ss := r.Header.Get("Accept-Encoding") ss := r.Header.Get("Accept-Encoding")
ss = strings.ToLower(ss) ss = strings.ToLower(ss)
...@@ -181,8 +199,10 @@ func GetAcceptEncodingZip(r *http.Request) string { ...@@ -181,8 +199,10 @@ func GetAcceptEncodingZip(r *http.Request) string {
} else { } else {
return "" return ""
} }
return ""
} }
// CloseZWriter closes the io.Writer after compressing static file.
func CloseZWriter(zwriter io.Writer) { func CloseZWriter(zwriter io.Writer) {
if zwriter == nil { if zwriter == nil {
return return
......
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
) )
const ( const (
// An environment variable when restarting application http listener.
FDKey = "BEEGO_HOT_FD" FDKey = "BEEGO_HOT_FD"
) )
...@@ -32,6 +33,7 @@ type conn struct { ...@@ -32,6 +33,7 @@ type conn struct {
lock sync.Mutex lock sync.Mutex
} }
// Close current processing connection.
func (c conn) Close() error { func (c conn) Close() error {
c.lock.Lock() c.lock.Lock()
defer c.lock.Unlock() defer c.lock.Unlock()
...@@ -67,6 +69,8 @@ func newStoppable(l net.Listener) (sl *stoppableListener) { ...@@ -67,6 +69,8 @@ func newStoppable(l net.Listener) (sl *stoppableListener) {
return return
} }
// Set stopped Listener to accept requests again.
// it returns the accepted and closable connection or error.
func (sl *stoppableListener) Accept() (c net.Conn, err error) { func (sl *stoppableListener) Accept() (c net.Conn, err error) {
c, err = sl.Listener.Accept() c, err = sl.Listener.Accept()
if err != nil { if err != nil {
...@@ -80,6 +84,7 @@ func (sl *stoppableListener) Accept() (c net.Conn, err error) { ...@@ -80,6 +84,7 @@ func (sl *stoppableListener) Accept() (c net.Conn, err error) {
return return
} }
// Listener waits signal to kill or interrupt then restart.
func WaitSignal(l net.Listener) error { func WaitSignal(l net.Listener) error {
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, os.Kill) signal.Notify(ch, os.Interrupt, os.Kill)
...@@ -101,6 +106,7 @@ func WaitSignal(l net.Listener) error { ...@@ -101,6 +106,7 @@ func WaitSignal(l net.Listener) error {
return nil // It'll never get here. return nil // It'll never get here.
} }
// Kill current running os process.
func CloseSelf() error { func CloseSelf() error {
ppid := os.Getpid() ppid := os.Getpid()
if ppid == 1 { // init provided sockets, for example systemd if ppid == 1 { // init provided sockets, for example systemd
...@@ -140,7 +146,8 @@ func Restart(l net.Listener) error { ...@@ -140,7 +146,8 @@ func Restart(l net.Listener) error {
return nil return nil
} }
func GetInitListner(tcpaddr *net.TCPAddr) (l net.Listener, err error) { // Get current net.Listen in running process.
func GetInitListener(tcpaddr *net.TCPAddr) (l net.Listener, err error) {
countStr := os.Getenv(FDKey) countStr := os.Getenv(FDKey)
if countStr == "" { if countStr == "" {
return net.ListenTCP("tcp", tcpaddr) return net.ListenTCP("tcp", tcpaddr)
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
) )
const ( const (
// default filter execution points
BeforeRouter = iota BeforeRouter = iota
AfterStatic AfterStatic
BeforeExec BeforeExec
...@@ -27,6 +28,7 @@ const ( ...@@ -27,6 +28,7 @@ const (
) )
var ( var (
// supported http methods.
HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"} HTTPMETHOD = []string{"get", "post", "put", "delete", "patch", "options", "head"}
) )
...@@ -39,6 +41,7 @@ type controllerInfo struct { ...@@ -39,6 +41,7 @@ type controllerInfo struct {
hasMethod bool hasMethod bool
} }
// ControllerRegistor containers registered router rules, controller handlers and filters.
type ControllerRegistor struct { type ControllerRegistor struct {
routers []*controllerInfo // regexp router storage routers []*controllerInfo // regexp router storage
fixrouters []*controllerInfo // fixed router storage fixrouters []*controllerInfo // fixed router storage
...@@ -48,6 +51,7 @@ type ControllerRegistor struct { ...@@ -48,6 +51,7 @@ type ControllerRegistor struct {
autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type autoRouter map[string]map[string]reflect.Type //key:controller key:method value:reflect.type
} }
// NewControllerRegistor returns a new ControllerRegistor.
func NewControllerRegistor() *ControllerRegistor { func NewControllerRegistor() *ControllerRegistor {
return &ControllerRegistor{ return &ControllerRegistor{
routers: make([]*controllerInfo, 0), routers: make([]*controllerInfo, 0),
...@@ -56,15 +60,16 @@ func NewControllerRegistor() *ControllerRegistor { ...@@ -56,15 +60,16 @@ func NewControllerRegistor() *ControllerRegistor {
} }
} }
//methods support like this: // Add controller handler and pattern rules to ControllerRegistor.
//default methods is the same name as method // usage:
//Add("/user",&UserController{}) // default methods is the same name as method
//Add("/api/list",&RestController{},"*:ListFood") // Add("/user",&UserController{})
//Add("/api/create",&RestController{},"post:CreateFood") // Add("/api/list",&RestController{},"*:ListFood")
//Add("/api/update",&RestController{},"put:UpdateFood") // Add("/api/create",&RestController{},"post:CreateFood")
//Add("/api/delete",&RestController{},"delete:DeleteFood") // Add("/api/update",&RestController{},"put:UpdateFood")
//Add("/api",&RestController{},"get,post:ApiFunc") // Add("/api/delete",&RestController{},"delete:DeleteFood")
//Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc") // Add("/api",&RestController{},"get,post:ApiFunc")
// Add("/simple",&SimpleController{},"get:GetFunc;post:PostFunc")
func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) { func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingMethods ...string) {
parts := strings.Split(pattern, "/") parts := strings.Split(pattern, "/")
...@@ -210,11 +215,11 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM ...@@ -210,11 +215,11 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
} }
} }
// add auto router to controller // Add auto router to ControllerRegistor.
// example beego.AddAuto(&MainContorlller{}) // example beego.AddAuto(&MainContorlller{}),
// MainController has method List and Page // MainController has method List and Page.
// you can visit the url /main/list to exec List function // visit the url /main/list to exec List function
// /main/page to exec Page function // /main/page to exec Page function.
func (p *ControllerRegistor) AddAuto(c ControllerInterface) { func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
p.enableAuto = true p.enableAuto = true
reflectVal := reflect.ValueOf(c) reflectVal := reflect.ValueOf(c)
...@@ -231,6 +236,8 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) { ...@@ -231,6 +236,8 @@ func (p *ControllerRegistor) AddAuto(c ControllerInterface) {
} }
} }
// [Deprecated] use InsertFilter.
// Add FilterFunc with pattern for action.
func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) { func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc) {
mr := buildFilter(pattern, filter) mr := buildFilter(pattern, filter)
switch action { switch action {
...@@ -248,12 +255,15 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc ...@@ -248,12 +255,15 @@ func (p *ControllerRegistor) AddFilter(pattern, action string, filter FilterFunc
p.enableFilter = true p.enableFilter = true
} }
// Add a FilterFunc with pattern rule and action constant.
func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) { func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) {
mr := buildFilter(pattern, filter) mr := buildFilter(pattern, filter)
p.filters[pos] = append(p.filters[pos], mr) p.filters[pos] = append(p.filters[pos], mr)
p.enableFilter = true p.enableFilter = true
} }
// UrlFor does another controller handler in this request function.
// it can access any controller method.
func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
paths := strings.Split(endpoint, ".") paths := strings.Split(endpoint, ".")
if len(paths) <= 1 { if len(paths) <= 1 {
...@@ -369,7 +379,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string { ...@@ -369,7 +379,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
return "" return ""
} }
// main function to serveHTTP // Implement http.Handler interface.
func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) { func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
...@@ -753,8 +763,8 @@ Admin: ...@@ -753,8 +763,8 @@ Admin:
} }
} }
// there always should be error handler that sets error code accordingly for all unhandled errors // there always should be error handler that sets error code accordingly for all unhandled errors.
// in order to have custom UI for error page it's necessary to override "500" error // in order to have custom UI for error page it's necessary to override "500" error.
func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.ResponseWriter, r *http.Request) { func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.ResponseWriter, r *http.Request) {
handler := middleware.SimpleServerError handler := middleware.SimpleServerError
ok := true ok := true
...@@ -771,6 +781,9 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp ...@@ -771,6 +781,9 @@ func (p *ControllerRegistor) getErrorHandler(errorCode string) func(rw http.Resp
return handler return handler
} }
// returns method name from request header or form field.
// sometimes browsers can't create PUT and DELETE request.
// set a form field "_method" instead.
func (p *ControllerRegistor) getRunMethod(method string, context *beecontext.Context, router *controllerInfo) string { func (p *ControllerRegistor) getRunMethod(method string, context *beecontext.Context, router *controllerInfo) string {
method = strings.ToLower(method) method = strings.ToLower(method)
if method == "post" && strings.ToLower(context.Input.Query("_method")) == "put" { if method == "post" && strings.ToLower(context.Input.Query("_method")) == "put" {
...@@ -806,6 +819,7 @@ func (w *responseWriter) Header() http.Header { ...@@ -806,6 +819,7 @@ func (w *responseWriter) Header() http.Header {
return w.writer.Header() return w.writer.Header()
} }
// Init content-length header.
func (w *responseWriter) InitHeadContent(contentlength int64) { func (w *responseWriter) InitHeadContent(contentlength int64) {
if w.contentEncoding == "gzip" { if w.contentEncoding == "gzip" {
w.Header().Set("Content-Encoding", "gzip") w.Header().Set("Content-Encoding", "gzip")
...@@ -817,14 +831,15 @@ func (w *responseWriter) InitHeadContent(contentlength int64) { ...@@ -817,14 +831,15 @@ func (w *responseWriter) InitHeadContent(contentlength int64) {
} }
// Write writes the data to the connection as part of an HTTP reply, // Write writes the data to the connection as part of an HTTP reply,
// and sets `started` to true // and sets `started` to true.
// started means the response has sent out.
func (w *responseWriter) Write(p []byte) (int, error) { func (w *responseWriter) Write(p []byte) (int, error) {
w.started = true w.started = true
return w.writer.Write(p) return w.writer.Write(p)
} }
// WriteHeader sends an HTTP response header with status code, // WriteHeader sends an HTTP response header with status code,
// and sets `started` to true // and sets `started` to true.
func (w *responseWriter) WriteHeader(code int) { func (w *responseWriter) WriteHeader(code int) {
w.status = code w.status = code
w.started = true w.started = true
......
...@@ -17,8 +17,9 @@ import ( ...@@ -17,8 +17,9 @@ import (
var ( var (
beegoTplFuncMap template.FuncMap beegoTplFuncMap template.FuncMap
BeeTemplates map[string]*template.Template // beego template caching map ans supported template file extensions.
BeeTemplateExt []string BeeTemplates map[string]*template.Template
BeeTemplateExt []string
) )
func init() { func init() {
...@@ -50,7 +51,7 @@ func init() { ...@@ -50,7 +51,7 @@ func init() {
beegoTplFuncMap["urlfor"] = UrlFor // != beegoTplFuncMap["urlfor"] = UrlFor // !=
} }
// AddFuncMap let user to register a func in the template // AddFuncMap let user to register a func in the template.
func AddFuncMap(key string, funname interface{}) error { func AddFuncMap(key string, funname interface{}) error {
beegoTplFuncMap[key] = funname beegoTplFuncMap[key] = funname
return nil return nil
...@@ -88,6 +89,7 @@ func (self *templatefile) visit(paths string, f os.FileInfo, err error) error { ...@@ -88,6 +89,7 @@ func (self *templatefile) visit(paths string, f os.FileInfo, err error) error {
return nil return nil
} }
// return this path has supported template extension of beego or not.
func HasTemplateExt(paths string) bool { func HasTemplateExt(paths string) bool {
for _, v := range BeeTemplateExt { for _, v := range BeeTemplateExt {
if strings.HasSuffix(paths, "."+v) { if strings.HasSuffix(paths, "."+v) {
...@@ -97,6 +99,7 @@ func HasTemplateExt(paths string) bool { ...@@ -97,6 +99,7 @@ func HasTemplateExt(paths string) bool {
return false return false
} }
// add new extension for template.
func AddTemplateExt(ext string) { func AddTemplateExt(ext string) {
for _, v := range BeeTemplateExt { for _, v := range BeeTemplateExt {
if v == ext { if v == ext {
...@@ -106,6 +109,8 @@ func AddTemplateExt(ext string) { ...@@ -106,6 +109,8 @@ func AddTemplateExt(ext string) {
BeeTemplateExt = append(BeeTemplateExt, ext) BeeTemplateExt = append(BeeTemplateExt, ext)
} }
// build all template files in a directory.
// it makes beego can render any template file in view directory.
func BuildTemplate(dir string) error { func BuildTemplate(dir string) error {
if _, err := os.Stat(dir); err != nil { if _, err := os.Stat(dir); err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
......
...@@ -12,7 +12,7 @@ import ( ...@@ -12,7 +12,7 @@ import (
"time" "time"
) )
// Substr() return the substr from start to length // Substr returns the substr from start to length.
func Substr(s string, start, length int) string { func Substr(s string, start, length int) string {
bt := []rune(s) bt := []rune(s)
if start < 0 { if start < 0 {
...@@ -27,7 +27,7 @@ func Substr(s string, start, length int) string { ...@@ -27,7 +27,7 @@ func Substr(s string, start, length int) string {
return string(bt[start:end]) return string(bt[start:end])
} }
// Html2str() returns escaping text convert from html // Html2str returns escaping text convert from html.
func Html2str(html string) string { func Html2str(html string) string {
src := string(html) src := string(html)
...@@ -60,6 +60,7 @@ func DateFormat(t time.Time, layout string) (datestring string) { ...@@ -60,6 +60,7 @@ func DateFormat(t time.Time, layout string) (datestring string) {
return return
} }
// DateFormat pattern rules.
var DatePatterns = []string{ var DatePatterns = []string{
// year // year
"Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003 "Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
...@@ -100,14 +101,14 @@ var DatePatterns = []string{ ...@@ -100,14 +101,14 @@ var DatePatterns = []string{
"r", time.RFC1123Z, "r", time.RFC1123Z,
} }
// Parse Date use PHP time format // Parse Date use PHP time format.
func DateParse(dateString, format string) (time.Time, error) { func DateParse(dateString, format string) (time.Time, error) {
replacer := strings.NewReplacer(DatePatterns...) replacer := strings.NewReplacer(DatePatterns...)
format = replacer.Replace(format) format = replacer.Replace(format)
return time.ParseInLocation(format, dateString, time.Local) return time.ParseInLocation(format, dateString, time.Local)
} }
// Date takes a PHP like date func to Go's time format // Date takes a PHP like date func to Go's time format.
func Date(t time.Time, format string) string { func Date(t time.Time, format string) string {
replacer := strings.NewReplacer(DatePatterns...) replacer := strings.NewReplacer(DatePatterns...)
format = replacer.Replace(format) format = replacer.Replace(format)
...@@ -115,7 +116,7 @@ func Date(t time.Time, format string) string { ...@@ -115,7 +116,7 @@ func Date(t time.Time, format string) string {
} }
// Compare is a quick and dirty comparison function. It will convert whatever you give it to strings and see if the two values are equal. // Compare is a quick and dirty comparison function. It will convert whatever you give it to strings and see if the two values are equal.
// Whitespace is trimmed. Used by the template parser as "eq" // Whitespace is trimmed. Used by the template parser as "eq".
func Compare(a, b interface{}) (equal bool) { func Compare(a, b interface{}) (equal bool) {
equal = false equal = false
if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) { if strings.TrimSpace(fmt.Sprintf("%v", a)) == strings.TrimSpace(fmt.Sprintf("%v", b)) {
...@@ -124,10 +125,12 @@ func Compare(a, b interface{}) (equal bool) { ...@@ -124,10 +125,12 @@ func Compare(a, b interface{}) (equal bool) {
return return
} }
// Convert string to template.HTML type.
func Str2html(raw string) template.HTML { func Str2html(raw string) template.HTML {
return template.HTML(raw) return template.HTML(raw)
} }
// Htmlquote returns quoted html string.
func Htmlquote(src string) string { func Htmlquote(src string) string {
//HTML编码为实体符号 //HTML编码为实体符号
/* /*
...@@ -150,6 +153,7 @@ func Htmlquote(src string) string { ...@@ -150,6 +153,7 @@ func Htmlquote(src string) string {
return strings.TrimSpace(text) return strings.TrimSpace(text)
} }
// Htmlunquote returns unquoted html string.
func Htmlunquote(src string) string { func Htmlunquote(src string) string {
//实体符号解释为HTML //实体符号解释为HTML
/* /*
...@@ -174,13 +178,14 @@ func Htmlunquote(src string) string { ...@@ -174,13 +178,14 @@ func Htmlunquote(src string) string {
return strings.TrimSpace(text) return strings.TrimSpace(text)
} }
// This will reference the index function local to the current blueprint: // UrlFor returns url string with another registered controller handler with params.
// usage:
// UrlFor(".index") // UrlFor(".index")
// ... print UrlFor("index") // print UrlFor("index")
// ... print UrlFor("login") // print UrlFor("login")
// ... print UrlFor("login", "next","/"") // print UrlFor("login", "next","/"")
// ... print UrlFor("profile", "username","John Doe") // print UrlFor("profile", "username","John Doe")
// ... // result:
// / // /
// /login // /login
// /login?next=/ // /login?next=/
...@@ -189,7 +194,7 @@ func UrlFor(endpoint string, values ...string) string { ...@@ -189,7 +194,7 @@ func UrlFor(endpoint string, values ...string) string {
return BeeApp.UrlFor(endpoint, values...) return BeeApp.UrlFor(endpoint, values...)
} }
//This can be changed to a better name // returns script tag with src string.
func AssetsJs(src string) template.HTML { func AssetsJs(src string) template.HTML {
text := string(src) text := string(src)
...@@ -198,7 +203,7 @@ func AssetsJs(src string) template.HTML { ...@@ -198,7 +203,7 @@ func AssetsJs(src string) template.HTML {
return template.HTML(text) return template.HTML(text)
} }
//This can be changed to a better name // returns stylesheet link tag with str string.
func AssetsCss(src string) template.HTML { func AssetsCss(src string) template.HTML {
text := string(src) text := string(src)
...@@ -207,7 +212,7 @@ func AssetsCss(src string) template.HTML { ...@@ -207,7 +212,7 @@ func AssetsCss(src string) template.HTML {
return template.HTML(text) return template.HTML(text)
} }
// parse form values to struct via tag // parse form values to struct via tag.
func ParseForm(form url.Values, obj interface{}) error { func ParseForm(form url.Values, obj interface{}) error {
objT := reflect.TypeOf(obj) objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj) objV := reflect.ValueOf(obj)
...@@ -295,7 +300,8 @@ var unKind = map[reflect.Kind]bool{ ...@@ -295,7 +300,8 @@ var unKind = map[reflect.Kind]bool{
reflect.UnsafePointer: true, reflect.UnsafePointer: true,
} }
// obj must be a struct pointer // render object to form html.
// obj must be a struct pointer.
func RenderForm(obj interface{}) template.HTML { func RenderForm(obj interface{}) template.HTML {
objT := reflect.TypeOf(obj) objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj) objV := reflect.ValueOf(obj)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment