mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 22:40:55 +00:00
Merge remote-tracking branch 'astaxie.beego/master'
This commit is contained in:
commit
9f2327ee57
9
admin.go
9
admin.go
@ -40,7 +40,14 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AdminIndex(rw http.ResponseWriter, r *http.Request) {
|
func AdminIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
rw.Write([]byte("Welcome to Admin Dashboard"))
|
rw.Write([]byte("Welcome to Admin Dashboard\n"))
|
||||||
|
rw.Write([]byte("There are servral functions:\n"))
|
||||||
|
rw.Write([]byte("1. Record all request and request time, http://localhost:8088/qps\n"))
|
||||||
|
rw.Write([]byte("2. Get runtime profiling data by the pprof, http://localhost:8088/prof\n"))
|
||||||
|
rw.Write([]byte("3. Get healthcheck result from http://localhost:8088/prof\n"))
|
||||||
|
rw.Write([]byte("4. Get current task infomation from taskhttp://localhost:8088/task \n"))
|
||||||
|
rw.Write([]byte("5. To run a task passed a param http://localhost:8088/runtask\n"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func QpsIndex(rw http.ResponseWriter, r *http.Request) {
|
func QpsIndex(rw http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -3,6 +3,7 @@ package beego
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
|
"crypto/rand"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
@ -370,7 +371,7 @@ func (c *Controller) XsrfToken() string {
|
|||||||
} else {
|
} else {
|
||||||
expire = int64(XSRFExpire)
|
expire = int64(XSRFExpire)
|
||||||
}
|
}
|
||||||
token = GetRandomString(15)
|
token = getRandomString(15)
|
||||||
c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire)
|
c.SetSecureCookie(XSRFKEY, "_xsrf", token, expire)
|
||||||
}
|
}
|
||||||
c._xsrf_token = token
|
c._xsrf_token = token
|
||||||
@ -405,3 +406,14 @@ func (c *Controller) GoToFunc(funcname string) {
|
|||||||
}
|
}
|
||||||
c.gotofunc = funcname
|
c.gotofunc = funcname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//utils func for controller internal
|
||||||
|
func getRandomString(n int) string {
|
||||||
|
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
var bytes = make([]byte, n)
|
||||||
|
rand.Read(bytes)
|
||||||
|
for i, b := range bytes {
|
||||||
|
bytes[i] = alphanum[b%byte(len(alphanum))]
|
||||||
|
}
|
||||||
|
return string(bytes)
|
||||||
|
}
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
beecontext "github.com/astaxie/beego/context"
|
beecontext "github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/middleware"
|
"github.com/astaxie/beego/middleware"
|
||||||
"github.com/astaxie/beego/toolbox"
|
"github.com/astaxie/beego/toolbox"
|
||||||
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -159,7 +160,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
|
|||||||
}
|
}
|
||||||
comma := strings.Split(colon[0], ",")
|
comma := strings.Split(colon[0], ",")
|
||||||
for _, m := range comma {
|
for _, m := range comma {
|
||||||
if m == "*" || inSlice(strings.ToLower(m), HTTPMETHOD) {
|
if m == "*" || utils.InSlice(strings.ToLower(m), HTTPMETHOD) {
|
||||||
if val := reflectVal.MethodByName(colon[1]); val.IsValid() {
|
if val := reflectVal.MethodByName(colon[1]); val.IsValid() {
|
||||||
methods[strings.ToLower(m)] = colon[1]
|
methods[strings.ToLower(m)] = colon[1]
|
||||||
} else {
|
} else {
|
||||||
@ -272,7 +273,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
|
|||||||
for _, route := range p.fixrouters {
|
for _, route := range p.fixrouters {
|
||||||
if route.controllerType.Name() == controllName {
|
if route.controllerType.Name() == controllName {
|
||||||
var finded bool
|
var finded bool
|
||||||
if inSlice(strings.ToLower(methodName), HTTPMETHOD) {
|
if utils.InSlice(strings.ToLower(methodName), HTTPMETHOD) {
|
||||||
if route.hasMethod {
|
if route.hasMethod {
|
||||||
if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
|
if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
|
||||||
finded = false
|
finded = false
|
||||||
@ -303,7 +304,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
|
|||||||
for _, route := range p.routers {
|
for _, route := range p.routers {
|
||||||
if route.controllerType.Name() == controllName {
|
if route.controllerType.Name() == controllName {
|
||||||
var finded bool
|
var finded bool
|
||||||
if inSlice(strings.ToLower(methodName), HTTPMETHOD) {
|
if utils.InSlice(strings.ToLower(methodName), HTTPMETHOD) {
|
||||||
if route.hasMethod {
|
if route.hasMethod {
|
||||||
if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
|
if m, ok := route.methods[strings.ToLower(methodName)]; ok && m != methodName {
|
||||||
finded = false
|
finded = false
|
||||||
@ -419,7 +420,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
context.Output = beecontext.NewOutput(rw)
|
context.Output = beecontext.NewOutput(rw)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !inSlice(strings.ToLower(r.Method), HTTPMETHOD) {
|
if !utils.InSlice(strings.ToLower(r.Method), HTTPMETHOD) {
|
||||||
http.Error(w, "Method Not Allowed", 405)
|
http.Error(w, "Method Not Allowed", 405)
|
||||||
goto Admin
|
goto Admin
|
||||||
}
|
}
|
||||||
|
158
template.go
158
template.go
@ -9,9 +9,10 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -144,7 +145,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
|
|||||||
} else {
|
} else {
|
||||||
fileabspath = filepath.Join(root, file)
|
fileabspath = filepath.Join(root, file)
|
||||||
}
|
}
|
||||||
if e, _ := FileExists(fileabspath); !e {
|
if e := utils.FileExists(fileabspath); !e {
|
||||||
panic("can't find template file" + file)
|
panic("can't find template file" + file)
|
||||||
}
|
}
|
||||||
data, err := ioutil.ReadFile(fileabspath)
|
data, err := ioutil.ReadFile(fileabspath)
|
||||||
@ -238,156 +239,3 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// go1.2 added template funcs. begin
|
|
||||||
var (
|
|
||||||
errBadComparisonType = errors.New("invalid type for comparison")
|
|
||||||
errBadComparison = errors.New("incompatible types for comparison")
|
|
||||||
errNoComparison = errors.New("missing argument for comparison")
|
|
||||||
)
|
|
||||||
|
|
||||||
type kind int
|
|
||||||
|
|
||||||
const (
|
|
||||||
invalidKind kind = iota
|
|
||||||
boolKind
|
|
||||||
complexKind
|
|
||||||
intKind
|
|
||||||
floatKind
|
|
||||||
integerKind
|
|
||||||
stringKind
|
|
||||||
uintKind
|
|
||||||
)
|
|
||||||
|
|
||||||
func basicKind(v reflect.Value) (kind, error) {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Bool:
|
|
||||||
return boolKind, nil
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
return intKind, nil
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
||||||
return uintKind, nil
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return floatKind, nil
|
|
||||||
case reflect.Complex64, reflect.Complex128:
|
|
||||||
return complexKind, nil
|
|
||||||
case reflect.String:
|
|
||||||
return stringKind, nil
|
|
||||||
}
|
|
||||||
return invalidKind, errBadComparisonType
|
|
||||||
}
|
|
||||||
|
|
||||||
// eq evaluates the comparison a == b || a == c || ...
|
|
||||||
func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
|
|
||||||
v1 := reflect.ValueOf(arg1)
|
|
||||||
k1, err := basicKind(v1)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if len(arg2) == 0 {
|
|
||||||
return false, errNoComparison
|
|
||||||
}
|
|
||||||
for _, arg := range arg2 {
|
|
||||||
v2 := reflect.ValueOf(arg)
|
|
||||||
k2, err := basicKind(v2)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if k1 != k2 {
|
|
||||||
return false, errBadComparison
|
|
||||||
}
|
|
||||||
truth := false
|
|
||||||
switch k1 {
|
|
||||||
case boolKind:
|
|
||||||
truth = v1.Bool() == v2.Bool()
|
|
||||||
case complexKind:
|
|
||||||
truth = v1.Complex() == v2.Complex()
|
|
||||||
case floatKind:
|
|
||||||
truth = v1.Float() == v2.Float()
|
|
||||||
case intKind:
|
|
||||||
truth = v1.Int() == v2.Int()
|
|
||||||
case stringKind:
|
|
||||||
truth = v1.String() == v2.String()
|
|
||||||
case uintKind:
|
|
||||||
truth = v1.Uint() == v2.Uint()
|
|
||||||
default:
|
|
||||||
panic("invalid kind")
|
|
||||||
}
|
|
||||||
if truth {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ne evaluates the comparison a != b.
|
|
||||||
func ne(arg1, arg2 interface{}) (bool, error) {
|
|
||||||
// != is the inverse of ==.
|
|
||||||
equal, err := eq(arg1, arg2)
|
|
||||||
return !equal, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// lt evaluates the comparison a < b.
|
|
||||||
func lt(arg1, arg2 interface{}) (bool, error) {
|
|
||||||
v1 := reflect.ValueOf(arg1)
|
|
||||||
k1, err := basicKind(v1)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
v2 := reflect.ValueOf(arg2)
|
|
||||||
k2, err := basicKind(v2)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if k1 != k2 {
|
|
||||||
return false, errBadComparison
|
|
||||||
}
|
|
||||||
truth := false
|
|
||||||
switch k1 {
|
|
||||||
case boolKind, complexKind:
|
|
||||||
return false, errBadComparisonType
|
|
||||||
case floatKind:
|
|
||||||
truth = v1.Float() < v2.Float()
|
|
||||||
case intKind:
|
|
||||||
truth = v1.Int() < v2.Int()
|
|
||||||
case stringKind:
|
|
||||||
truth = v1.String() < v2.String()
|
|
||||||
case uintKind:
|
|
||||||
truth = v1.Uint() < v2.Uint()
|
|
||||||
default:
|
|
||||||
panic("invalid kind")
|
|
||||||
}
|
|
||||||
return truth, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// le evaluates the comparison <= b.
|
|
||||||
func le(arg1, arg2 interface{}) (bool, error) {
|
|
||||||
// <= is < or ==.
|
|
||||||
lessThan, err := lt(arg1, arg2)
|
|
||||||
if lessThan || err != nil {
|
|
||||||
return lessThan, err
|
|
||||||
}
|
|
||||||
return eq(arg1, arg2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// gt evaluates the comparison a > b.
|
|
||||||
func gt(arg1, arg2 interface{}) (bool, error) {
|
|
||||||
// > is the inverse of <=.
|
|
||||||
lessOrEqual, err := le(arg1, arg2)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return !lessOrEqual, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ge evaluates the comparison a >= b.
|
|
||||||
func ge(arg1, arg2 interface{}) (bool, error) {
|
|
||||||
// >= is the inverse of <.
|
|
||||||
lessThan, err := lt(arg1, arg2)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return !lessThan, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// go1.2 added template funcs. end
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -13,14 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func webTime(t time.Time) string {
|
// Substr() return the substr from start to length
|
||||||
ftime := t.Format(time.RFC1123)
|
|
||||||
if strings.HasSuffix(ftime, "UTC") {
|
|
||||||
ftime = ftime[0:len(ftime)-3] + "GMT"
|
|
||||||
}
|
|
||||||
return ftime
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
@ -182,13 +174,37 @@ func Htmlunquote(src string) string {
|
|||||||
return strings.TrimSpace(text)
|
return strings.TrimSpace(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func inSlice(v string, sl []string) bool {
|
// This will reference the index function local to the current blueprint:
|
||||||
for _, vv := range sl {
|
// UrlFor(".index")
|
||||||
if vv == v {
|
// ... print UrlFor("index")
|
||||||
return true
|
// ... print UrlFor("login")
|
||||||
}
|
// ... print UrlFor("login", "next","/"")
|
||||||
}
|
// ... print UrlFor("profile", "username","John Doe")
|
||||||
return false
|
// ...
|
||||||
|
// /
|
||||||
|
// /login
|
||||||
|
// /login?next=/
|
||||||
|
// /user/John%20Doe
|
||||||
|
func UrlFor(endpoint string, values ...string) string {
|
||||||
|
return BeeApp.UrlFor(endpoint, values...)
|
||||||
|
}
|
||||||
|
|
||||||
|
//This can be changed to a better name
|
||||||
|
func AssetsJs(src string) template.HTML {
|
||||||
|
text := string(src)
|
||||||
|
|
||||||
|
text = "<script src=\"" + src + "\"></script>"
|
||||||
|
|
||||||
|
return template.HTML(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
//This can be changed to a better name
|
||||||
|
func AssetsCss(src string) template.HTML {
|
||||||
|
text := string(src)
|
||||||
|
|
||||||
|
text = "<link href=\"" + src + "\" rel=\"stylesheet\" />"
|
||||||
|
|
||||||
|
return template.HTML(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse form values to struct via tag
|
// parse form values to struct via tag
|
||||||
@ -339,71 +355,155 @@ func isStructPtr(t reflect.Type) bool {
|
|||||||
return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
|
return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringsToJson(str string) string {
|
// go1.2 added template funcs. begin
|
||||||
rs := []rune(str)
|
var (
|
||||||
jsons := ""
|
errBadComparisonType = errors.New("invalid type for comparison")
|
||||||
for _, r := range rs {
|
errBadComparison = errors.New("incompatible types for comparison")
|
||||||
rint := int(r)
|
errNoComparison = errors.New("missing argument for comparison")
|
||||||
if rint < 128 {
|
)
|
||||||
jsons += string(r)
|
|
||||||
} else {
|
type kind int
|
||||||
jsons += "\\u" + strconv.FormatInt(int64(rint), 16) // json
|
|
||||||
|
const (
|
||||||
|
invalidKind kind = iota
|
||||||
|
boolKind
|
||||||
|
complexKind
|
||||||
|
intKind
|
||||||
|
floatKind
|
||||||
|
integerKind
|
||||||
|
stringKind
|
||||||
|
uintKind
|
||||||
|
)
|
||||||
|
|
||||||
|
func basicKind(v reflect.Value) (kind, error) {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
return boolKind, nil
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return intKind, nil
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return uintKind, nil
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return floatKind, nil
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
return complexKind, nil
|
||||||
|
case reflect.String:
|
||||||
|
return stringKind, nil
|
||||||
|
}
|
||||||
|
return invalidKind, errBadComparisonType
|
||||||
|
}
|
||||||
|
|
||||||
|
// eq evaluates the comparison a == b || a == c || ...
|
||||||
|
func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
|
||||||
|
v1 := reflect.ValueOf(arg1)
|
||||||
|
k1, err := basicKind(v1)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(arg2) == 0 {
|
||||||
|
return false, errNoComparison
|
||||||
|
}
|
||||||
|
for _, arg := range arg2 {
|
||||||
|
v2 := reflect.ValueOf(arg)
|
||||||
|
k2, err := basicKind(v2)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if k1 != k2 {
|
||||||
|
return false, errBadComparison
|
||||||
|
}
|
||||||
|
truth := false
|
||||||
|
switch k1 {
|
||||||
|
case boolKind:
|
||||||
|
truth = v1.Bool() == v2.Bool()
|
||||||
|
case complexKind:
|
||||||
|
truth = v1.Complex() == v2.Complex()
|
||||||
|
case floatKind:
|
||||||
|
truth = v1.Float() == v2.Float()
|
||||||
|
case intKind:
|
||||||
|
truth = v1.Int() == v2.Int()
|
||||||
|
case stringKind:
|
||||||
|
truth = v1.String() == v2.String()
|
||||||
|
case uintKind:
|
||||||
|
truth = v1.Uint() == v2.Uint()
|
||||||
|
default:
|
||||||
|
panic("invalid kind")
|
||||||
|
}
|
||||||
|
if truth {
|
||||||
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return jsons
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func FileExists(path string) (bool, error) {
|
// ne evaluates the comparison a != b.
|
||||||
_, err := os.Stat(path)
|
func ne(arg1, arg2 interface{}) (bool, error) {
|
||||||
if err == nil {
|
// != is the inverse of ==.
|
||||||
return true, nil
|
equal, err := eq(arg1, arg2)
|
||||||
|
return !equal, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// lt evaluates the comparison a < b.
|
||||||
|
func lt(arg1, arg2 interface{}) (bool, error) {
|
||||||
|
v1 := reflect.ValueOf(arg1)
|
||||||
|
k1, err := basicKind(v1)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
}
|
}
|
||||||
if os.IsNotExist(err) {
|
v2 := reflect.ValueOf(arg2)
|
||||||
return false, nil
|
k2, err := basicKind(v2)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
}
|
}
|
||||||
return false, err
|
if k1 != k2 {
|
||||||
}
|
return false, errBadComparison
|
||||||
|
|
||||||
func GetRandomString(n int) string {
|
|
||||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
||||||
var bytes = make([]byte, n)
|
|
||||||
rand.Read(bytes)
|
|
||||||
for i, b := range bytes {
|
|
||||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
|
||||||
}
|
}
|
||||||
return string(bytes)
|
truth := false
|
||||||
|
switch k1 {
|
||||||
|
case boolKind, complexKind:
|
||||||
|
return false, errBadComparisonType
|
||||||
|
case floatKind:
|
||||||
|
truth = v1.Float() < v2.Float()
|
||||||
|
case intKind:
|
||||||
|
truth = v1.Int() < v2.Int()
|
||||||
|
case stringKind:
|
||||||
|
truth = v1.String() < v2.String()
|
||||||
|
case uintKind:
|
||||||
|
truth = v1.Uint() < v2.Uint()
|
||||||
|
default:
|
||||||
|
panic("invalid kind")
|
||||||
|
}
|
||||||
|
return truth, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will reference the index function local to the current blueprint:
|
// le evaluates the comparison <= b.
|
||||||
// UrlFor(".index")
|
func le(arg1, arg2 interface{}) (bool, error) {
|
||||||
// ... print UrlFor("index")
|
// <= is < or ==.
|
||||||
// ... print UrlFor("login")
|
lessThan, err := lt(arg1, arg2)
|
||||||
// ... print UrlFor("login", "next","/"")
|
if lessThan || err != nil {
|
||||||
// ... print UrlFor("profile", "username","John Doe")
|
return lessThan, err
|
||||||
// ...
|
}
|
||||||
// /
|
return eq(arg1, arg2)
|
||||||
// /login
|
|
||||||
// /login?next=/
|
|
||||||
// /user/John%20Doe
|
|
||||||
func UrlFor(endpoint string, values ...string) string {
|
|
||||||
return BeeApp.UrlFor(endpoint, values...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gt evaluates the comparison a > b.
|
||||||
//This can be changed to a better name
|
func gt(arg1, arg2 interface{}) (bool, error) {
|
||||||
func AssetsJs(src string) template.HTML {
|
// > is the inverse of <=.
|
||||||
text := string(src)
|
lessOrEqual, err := le(arg1, arg2)
|
||||||
|
if err != nil {
|
||||||
text = "<script src=\""+src+"\"></script>"
|
return false, err
|
||||||
|
}
|
||||||
return template.HTML(text)
|
return !lessOrEqual, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//This can be changed to a better name
|
// ge evaluates the comparison a >= b.
|
||||||
func AssetsCss(src string) template.HTML {
|
func ge(arg1, arg2 interface{}) (bool, error) {
|
||||||
text := string(src)
|
// >= is the inverse of <.
|
||||||
|
lessThan, err := lt(arg1, arg2)
|
||||||
text = "<link href=\""+src+"\" rel=\"stylesheet\" />"
|
if err != nil {
|
||||||
|
return false, err
|
||||||
return template.HTML(text)
|
}
|
||||||
|
return !lessThan, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// go1.2 added template funcs. end
|
@ -7,18 +7,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWebTime(t *testing.T) {
|
|
||||||
ts := "Fri, 26 Jul 2013 12:27:42 CST"
|
|
||||||
l, _ := time.LoadLocation("GST")
|
|
||||||
tt, _ := time.ParseInLocation(time.RFC1123, ts, l)
|
|
||||||
if ts != webTime(tt) {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
if "Fri, 26 Jul 2013 12:27:42 GMT" != webTime(tt.UTC()) {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSubstr(t *testing.T) {
|
func TestSubstr(t *testing.T) {
|
||||||
s := `012345`
|
s := `012345`
|
||||||
if Substr(s, 0, 2) != "01" {
|
if Substr(s, 0, 2) != "01" {
|
||||||
@ -92,16 +80,6 @@ func TestHtmlunquote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInSlice(t *testing.T) {
|
|
||||||
sl := []string{"A", "b"}
|
|
||||||
if !inSlice("A", sl) {
|
|
||||||
t.Error("should be true")
|
|
||||||
}
|
|
||||||
if inSlice("B", sl) {
|
|
||||||
t.Error("should be false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseForm(t *testing.T) {
|
func TestParseForm(t *testing.T) {
|
||||||
type user struct {
|
type user struct {
|
||||||
Id int `form:"-"`
|
Id int `form:"-"`
|
@ -30,7 +30,7 @@ func FileExists(name string) bool {
|
|||||||
|
|
||||||
// search a file in paths.
|
// search a file in paths.
|
||||||
// this is offen used in search config file in /etc ~/
|
// this is offen used in search config file in /etc ~/
|
||||||
func LookFile(filename string, paths ...string) (fullpath string, err error) {
|
func SearchFile(filename string, paths ...string) (fullpath string, err error) {
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
if fullpath = filepath.Join(path, filename); FileExists(fullpath) {
|
if fullpath = filepath.Join(path, filename); FileExists(fullpath) {
|
||||||
return
|
return
|
||||||
@ -41,7 +41,7 @@ func LookFile(filename string, paths ...string) (fullpath string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// like command grep -E
|
// like command grep -E
|
||||||
// for example: GrepE(`^hello`, "hello.txt")
|
// for example: GrepFile(`^hello`, "hello.txt")
|
||||||
// \n is striped while read
|
// \n is striped while read
|
||||||
func GrepFile(patten string, filename string) (lines []string, err error) {
|
func GrepFile(patten string, filename string) (lines []string, err error) {
|
||||||
re, err := regexp.Compile(patten)
|
re, err := regexp.Compile(patten)
|
||||||
|
@ -23,7 +23,7 @@ func TestSelfDir(t *testing.T) {
|
|||||||
|
|
||||||
func TestFileExists(t *testing.T) {
|
func TestFileExists(t *testing.T) {
|
||||||
if !FileExists("./file.go") {
|
if !FileExists("./file.go") {
|
||||||
t.Errorf("/bin/echo should exists, but it didn't")
|
t.Errorf("./file.go should exists, but it didn't")
|
||||||
}
|
}
|
||||||
|
|
||||||
if FileExists(noExistedFile) {
|
if FileExists(noExistedFile) {
|
||||||
@ -31,14 +31,14 @@ func TestFileExists(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLookFile(t *testing.T) {
|
func TestSearchFile(t *testing.T) {
|
||||||
path, err := LookFile(filepath.Base(SelfPath()), SelfDir())
|
path, err := SearchFile(filepath.Base(SelfPath()), SelfDir())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
t.Log(path)
|
t.Log(path)
|
||||||
|
|
||||||
path, err = LookFile(noExistedFile, ".")
|
path, err = SearchFile(noExistedFile, ".")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("err shouldnot be nil, got path: %s", SelfDir())
|
t.Errorf("err shouldnot be nil, got path: %s", SelfDir())
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package beego
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
@ -1,4 +1,4 @@
|
|||||||
package beego
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
141
utils/slice.go
Normal file
141
utils/slice.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type reducetype func(interface{}) interface{}
|
||||||
|
type filtertype func(interface{}) bool
|
||||||
|
|
||||||
|
func InSlice(v string, sl []string) bool {
|
||||||
|
for _, vv := range sl {
|
||||||
|
if vv == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func InSliceIface(v interface{}, sl []interface{}) bool {
|
||||||
|
for _, vv := range sl {
|
||||||
|
if vv == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceRandList(min, max int) []int {
|
||||||
|
if max < min {
|
||||||
|
min, max = max, min
|
||||||
|
}
|
||||||
|
length := max - min + 1
|
||||||
|
t0 := time.Now()
|
||||||
|
rand.Seed(int64(t0.Nanosecond()))
|
||||||
|
list := rand.Perm(length)
|
||||||
|
for index, _ := range list {
|
||||||
|
list[index] += min
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) {
|
||||||
|
c = append(slice1, slice2...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) {
|
||||||
|
for _, v := range slice {
|
||||||
|
dslice = append(dslice, a(v))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceRand(a []interface{}) (b interface{}) {
|
||||||
|
randnum := rand.Intn(len(a))
|
||||||
|
b = a[randnum]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceSum(intslice []int64) (sum int64) {
|
||||||
|
for _, v := range intslice {
|
||||||
|
sum += v
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) {
|
||||||
|
for _, v := range slice {
|
||||||
|
if a(v) {
|
||||||
|
ftslice = append(ftslice, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) {
|
||||||
|
for _, v := range slice1 {
|
||||||
|
if !InSliceIface(v, slice2) {
|
||||||
|
diffslice = append(diffslice, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) {
|
||||||
|
for _, v := range slice1 {
|
||||||
|
if !InSliceIface(v, slice2) {
|
||||||
|
diffslice = append(diffslice, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) {
|
||||||
|
if size >= len(slice) {
|
||||||
|
chunkslice = append(chunkslice, slice)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
end := size
|
||||||
|
for i := 0; i <= (len(slice) - size); i += size {
|
||||||
|
chunkslice = append(chunkslice, slice[i:end])
|
||||||
|
end += size
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceRange(start, end, step int64) (intslice []int64) {
|
||||||
|
for i := start; i <= end; i += step {
|
||||||
|
intslice = append(intslice, i)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SlicePad(slice []interface{}, size int, val interface{}) []interface{} {
|
||||||
|
if size <= len(slice) {
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
for i := 0; i < (size - len(slice)); i++ {
|
||||||
|
slice = append(slice, val)
|
||||||
|
}
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceUnique(slice []interface{}) (uniqueslice []interface{}) {
|
||||||
|
for _, v := range slice {
|
||||||
|
if !InSliceIface(v, uniqueslice) {
|
||||||
|
uniqueslice = append(uniqueslice, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceShuffle(slice []interface{}) []interface{} {
|
||||||
|
for i := 0; i < len(slice); i++ {
|
||||||
|
a := rand.Intn(len(slice))
|
||||||
|
b := rand.Intn(len(slice))
|
||||||
|
slice[a], slice[b] = slice[b], slice[a]
|
||||||
|
}
|
||||||
|
return slice
|
||||||
|
}
|
15
utils/slice_test.go
Normal file
15
utils/slice_test.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInSlice(t *testing.T) {
|
||||||
|
sl := []string{"A", "b"}
|
||||||
|
if !InSlice("A", sl) {
|
||||||
|
t.Error("should be true")
|
||||||
|
}
|
||||||
|
if InSlice("B", sl) {
|
||||||
|
t.Error("should be false")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user