Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
B
beego
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
beego
Commits
9f2327ee
Commit
9f2327ee
authored
Dec 13, 2013
by
mingqi.zhou
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'astaxie.beego/master'
parents
68f2a5dd
b1374b6a
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
702 additions
and
600 deletions
+702
-600
admin.go
admin.go
+8
-1
controller.go
controller.go
+13
-1
router.go
router.go
+5
-4
template.go
template.go
+3
-155
templatefunc.go
templatefunc.go
+509
-409
templatefunc_test.go
templatefunc_test.go
+0
-22
file.go
utils/file.go
+2
-2
file_test.go
utils/file_test.go
+4
-4
safemap.go
utils/safemap.go
+1
-1
safemap_test.go
utils/safemap_test.go
+1
-1
slice.go
utils/slice.go
+141
-0
slice_test.go
utils/slice_test.go
+15
-0
No files found.
admin.go
View file @
9f2327ee
...
...
@@ -40,7 +40,14 @@ func init() {
}
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
)
{
...
...
controller.go
View file @
9f2327ee
...
...
@@ -3,6 +3,7 @@ package beego
import
(
"bytes"
"crypto/hmac"
"crypto/rand"
"crypto/sha1"
"encoding/base64"
"errors"
...
...
@@ -370,7 +371,7 @@ func (c *Controller) XsrfToken() string {
}
else
{
expire
=
int64
(
XSRFExpire
)
}
token
=
G
etRandomString
(
15
)
token
=
g
etRandomString
(
15
)
c
.
SetSecureCookie
(
XSRFKEY
,
"_xsrf"
,
token
,
expire
)
}
c
.
_xsrf_token
=
token
...
...
@@ -405,3 +406,14 @@ func (c *Controller) GoToFunc(funcname string) {
}
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
)
}
router.go
View file @
9f2327ee
...
...
@@ -15,6 +15,7 @@ import (
beecontext
"github.com/astaxie/beego/context"
"github.com/astaxie/beego/middleware"
"github.com/astaxie/beego/toolbox"
"github.com/astaxie/beego/utils"
)
const
(
...
...
@@ -159,7 +160,7 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface, mappingM
}
comma
:=
strings
.
Split
(
colon
[
0
],
","
)
for
_
,
m
:=
range
comma
{
if
m
==
"*"
||
i
nSlice
(
strings
.
ToLower
(
m
),
HTTPMETHOD
)
{
if
m
==
"*"
||
utils
.
I
nSlice
(
strings
.
ToLower
(
m
),
HTTPMETHOD
)
{
if
val
:=
reflectVal
.
MethodByName
(
colon
[
1
]);
val
.
IsValid
()
{
methods
[
strings
.
ToLower
(
m
)]
=
colon
[
1
]
}
else
{
...
...
@@ -272,7 +273,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
for
_
,
route
:=
range
p
.
fixrouters
{
if
route
.
controllerType
.
Name
()
==
controllName
{
var
finded
bool
if
i
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
utils
.
I
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
route
.
hasMethod
{
if
m
,
ok
:=
route
.
methods
[
strings
.
ToLower
(
methodName
)];
ok
&&
m
!=
methodName
{
finded
=
false
...
...
@@ -303,7 +304,7 @@ func (p *ControllerRegistor) UrlFor(endpoint string, values ...string) string {
for
_
,
route
:=
range
p
.
routers
{
if
route
.
controllerType
.
Name
()
==
controllName
{
var
finded
bool
if
i
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
utils
.
I
nSlice
(
strings
.
ToLower
(
methodName
),
HTTPMETHOD
)
{
if
route
.
hasMethod
{
if
m
,
ok
:=
route
.
methods
[
strings
.
ToLower
(
methodName
)];
ok
&&
m
!=
methodName
{
finded
=
false
...
...
@@ -419,7 +420,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
context
.
Output
=
beecontext
.
NewOutput
(
rw
)
}
if
!
i
nSlice
(
strings
.
ToLower
(
r
.
Method
),
HTTPMETHOD
)
{
if
!
utils
.
I
nSlice
(
strings
.
ToLower
(
r
.
Method
),
HTTPMETHOD
)
{
http
.
Error
(
w
,
"Method Not Allowed"
,
405
)
goto
Admin
}
...
...
template.go
View file @
9f2327ee
...
...
@@ -9,9 +9,10 @@ import (
"io/ioutil"
"os"
"path/filepath"
"reflect"
"regexp"
"strings"
"github.com/astaxie/beego/utils"
)
var
(
...
...
@@ -144,7 +145,7 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
}
else
{
fileabspath
=
filepath
.
Join
(
root
,
file
)
}
if
e
,
_
:=
FileExists
(
fileabspath
);
!
e
{
if
e
:=
utils
.
FileExists
(
fileabspath
);
!
e
{
panic
(
"can't find template file"
+
file
)
}
data
,
err
:=
ioutil
.
ReadFile
(
fileabspath
)
...
...
@@ -238,156 +239,3 @@ func _getTemplate(t0 *template.Template, root string, submods [][]string, others
}
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
utils
.go
→
templatefunc
.go
View file @
9f2327ee
package
beego
import
(
"crypto/rand"
"fmt"
"html/template"
"net/url"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"time"
)
func
webTime
(
t
time
.
Time
)
string
{
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
{
bt
:=
[]
rune
(
s
)
if
start
<
0
{
start
=
0
}
var
end
int
if
(
start
+
length
)
>
(
len
(
bt
)
-
1
)
{
end
=
len
(
bt
)
}
else
{
end
=
start
+
length
}
return
string
(
bt
[
start
:
end
])
}
// Html2str() returns escaping text convert from html
func
Html2str
(
html
string
)
string
{
src
:=
string
(
html
)
//将HTML标签全转换成小写
re
,
_
:=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllStringFunc
(
src
,
strings
.
ToLower
)
//去除STYLE
re
,
_
=
regexp
.
Compile
(
"
\\
<style[
\\
S
\\
s]+?
\\
</style
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除SCRIPT
re
,
_
=
regexp
.
Compile
(
"
\\
<script[
\\
S
\\
s]+?
\\
</script
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除所有尖括号内的HTML代码,并换成换行符
re
,
_
=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
//去除连续的换行符
re
,
_
=
regexp
.
Compile
(
"
\\
s{2,}"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
return
strings
.
TrimSpace
(
src
)
}
// DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat"
func
DateFormat
(
t
time
.
Time
,
layout
string
)
(
datestring
string
)
{
datestring
=
t
.
Format
(
layout
)
return
}
var
DatePatterns
=
[]
string
{
// year
"Y"
,
"2006"
,
// A full numeric representation of a year, 4 digits Examples: 1999 or 2003
"y"
,
"06"
,
//A two digit representation of a year Examples: 99 or 03
// month
"m"
,
"01"
,
// Numeric representation of a month, with leading zeros 01 through 12
"n"
,
"1"
,
// Numeric representation of a month, without leading zeros 1 through 12
"M"
,
"Jan"
,
// A short textual representation of a month, three letters Jan through Dec
"F"
,
"January"
,
// A full textual representation of a month, such as January or March January through December
// day
"d"
,
"02"
,
// Day of the month, 2 digits with leading zeros 01 to 31
"j"
,
"2"
,
// Day of the month without leading zeros 1 to 31
// week
"D"
,
"Mon"
,
// A textual representation of a day, three letters Mon through Sun
"l"
,
"Monday"
,
// A full textual representation of the day of the week Sunday through Saturday
// time
"g"
,
"3"
,
// 12-hour format of an hour without leading zeros 1 through 12
"G"
,
"15"
,
// 24-hour format of an hour without leading zeros 0 through 23
"h"
,
"03"
,
// 12-hour format of an hour with leading zeros 01 through 12
"H"
,
"15"
,
// 24-hour format of an hour with leading zeros 00 through 23
"a"
,
"pm"
,
// Lowercase Ante meridiem and Post meridiem am or pm
"A"
,
"PM"
,
// Uppercase Ante meridiem and Post meridiem AM or PM
"i"
,
"04"
,
// Minutes with leading zeros 00 to 59
"s"
,
"05"
,
// Seconds, with leading zeros 00 through 59
// time zone
"T"
,
"MST"
,
"P"
,
"-07:00"
,
"O"
,
"-0700"
,
// RFC 2822
"r"
,
time
.
RFC1123Z
,
}
// Parse Date use PHP time format
func
DateParse
(
dateString
,
format
string
)
(
time
.
Time
,
error
)
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
time
.
ParseInLocation
(
format
,
dateString
,
time
.
Local
)
}
// Date takes a PHP like date func to Go's time format
func
Date
(
t
time
.
Time
,
format
string
)
string
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
t
.
Format
(
format
)
}
// 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"
func
Compare
(
a
,
b
interface
{})
(
equal
bool
)
{
equal
=
false
if
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
a
))
==
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
b
))
{
equal
=
true
}
return
}
func
Str2html
(
raw
string
)
template
.
HTML
{
return
template
.
HTML
(
raw
)
}
func
Htmlquote
(
src
string
)
string
{
//HTML编码为实体符号
/*
Encodes `text` for raw use in HTML.
>>> htmlquote("<'&\\">")
'<'&">'
*/
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done first!
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"
\"
"
,
"""
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
return
strings
.
TrimSpace
(
text
)
}
func
Htmlunquote
(
src
string
)
string
{
//实体符号解释为HTML
/*
Decodes `text` that's HTML quoted.
>>> htmlunquote('<'&">')
'<\\'&">'
*/
// strings.Replace(s, old, new, n)
// 在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"""
,
"
\"
"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done last!
return
strings
.
TrimSpace
(
text
)
}
func
inSlice
(
v
string
,
sl
[]
string
)
bool
{
for
_
,
vv
:=
range
sl
{
if
vv
==
v
{
return
true
}
}
return
false
}
// parse form values to struct via tag
func
ParseForm
(
form
url
.
Values
,
obj
interface
{})
error
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
fmt
.
Errorf
(
"%v must be a struct pointer"
,
obj
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
var
tag
string
if
len
(
tags
)
==
0
||
len
(
tags
[
0
])
==
0
{
tag
=
fieldT
.
Name
}
else
if
tags
[
0
]
==
"-"
{
continue
}
else
{
tag
=
tags
[
0
]
}
value
:=
form
.
Get
(
tag
)
if
len
(
value
)
==
0
{
continue
}
switch
fieldT
.
Type
.
Kind
()
{
case
reflect
.
Bool
:
b
,
err
:=
strconv
.
ParseBool
(
value
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetBool
(
b
)
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
x
,
err
:=
strconv
.
ParseInt
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetInt
(
x
)
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
:
x
,
err
:=
strconv
.
ParseUint
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetUint
(
x
)
case
reflect
.
Float32
,
reflect
.
Float64
:
x
,
err
:=
strconv
.
ParseFloat
(
value
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetFloat
(
x
)
case
reflect
.
Interface
:
fieldV
.
Set
(
reflect
.
ValueOf
(
value
))
case
reflect
.
String
:
fieldV
.
SetString
(
value
)
}
}
return
nil
}
// form types for RenderForm function
var
FormType
=
map
[
string
]
bool
{
"text"
:
true
,
"textarea"
:
true
,
"hidden"
:
true
,
"password"
:
true
,
}
var
unKind
=
map
[
reflect
.
Kind
]
bool
{
reflect
.
Uintptr
:
true
,
reflect
.
Complex64
:
true
,
reflect
.
Complex128
:
true
,
reflect
.
Array
:
true
,
reflect
.
Chan
:
true
,
reflect
.
Func
:
true
,
reflect
.
Map
:
true
,
reflect
.
Ptr
:
true
,
reflect
.
Slice
:
true
,
reflect
.
Struct
:
true
,
reflect
.
UnsafePointer
:
true
,
}
// obj must be a struct pointer
func
RenderForm
(
obj
interface
{})
template
.
HTML
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
template
.
HTML
(
""
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
var
raw
[]
string
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
||
unKind
[
fieldV
.
Kind
()]
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
label
:=
fieldT
.
Name
+
": "
name
:=
fieldT
.
Name
fType
:=
"text"
switch
len
(
tags
)
{
case
1
:
if
tags
[
0
]
==
"-"
{
continue
}
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
case
2
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
case
3
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
if
len
(
tags
[
2
])
>
0
{
label
=
tags
[
2
]
}
}
raw
=
append
(
raw
,
fmt
.
Sprintf
(
`%v<input name="%v" type="%v" value="%v">`
,
label
,
name
,
fType
,
fieldV
.
Interface
()))
}
return
template
.
HTML
(
strings
.
Join
(
raw
,
"</br>"
))
}
func
isStructPtr
(
t
reflect
.
Type
)
bool
{
return
t
.
Kind
()
==
reflect
.
Ptr
&&
t
.
Elem
()
.
Kind
()
==
reflect
.
Struct
}
func
stringsToJson
(
str
string
)
string
{
rs
:=
[]
rune
(
str
)
jsons
:=
""
for
_
,
r
:=
range
rs
{
rint
:=
int
(
r
)
if
rint
<
128
{
jsons
+=
string
(
r
)
}
else
{
jsons
+=
"
\\
u"
+
strconv
.
FormatInt
(
int64
(
rint
),
16
)
// json
}
}
return
jsons
}
func
FileExists
(
path
string
)
(
bool
,
error
)
{
_
,
err
:=
os
.
Stat
(
path
)
if
err
==
nil
{
return
true
,
nil
}
if
os
.
IsNotExist
(
err
)
{
return
false
,
nil
}
return
false
,
err
}
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
)
}
// This will reference the index function local to the current blueprint:
// UrlFor(".index")
// ... print UrlFor("index")
// ... print UrlFor("login")
// ... print UrlFor("login", "next","/"")
// ... print UrlFor("profile", "username","John Doe")
// ...
// /
// /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
)
}
package
beego
import
(
"errors"
"fmt"
"html/template"
"net/url"
"reflect"
"regexp"
"strconv"
"strings"
"time"
)
// Substr() return the substr from start to length
func
Substr
(
s
string
,
start
,
length
int
)
string
{
bt
:=
[]
rune
(
s
)
if
start
<
0
{
start
=
0
}
var
end
int
if
(
start
+
length
)
>
(
len
(
bt
)
-
1
)
{
end
=
len
(
bt
)
}
else
{
end
=
start
+
length
}
return
string
(
bt
[
start
:
end
])
}
// Html2str() returns escaping text convert from html
func
Html2str
(
html
string
)
string
{
src
:=
string
(
html
)
//将HTML标签全转换成小写
re
,
_
:=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllStringFunc
(
src
,
strings
.
ToLower
)
//去除STYLE
re
,
_
=
regexp
.
Compile
(
"
\\
<style[
\\
S
\\
s]+?
\\
</style
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除SCRIPT
re
,
_
=
regexp
.
Compile
(
"
\\
<script[
\\
S
\\
s]+?
\\
</script
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
""
)
//去除所有尖括号内的HTML代码,并换成换行符
re
,
_
=
regexp
.
Compile
(
"
\\
<[
\\
S
\\
s]+?
\\
>"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
//去除连续的换行符
re
,
_
=
regexp
.
Compile
(
"
\\
s{2,}"
)
src
=
re
.
ReplaceAllString
(
src
,
"
\n
"
)
return
strings
.
TrimSpace
(
src
)
}
// DateFormat takes a time and a layout string and returns a string with the formatted date. Used by the template parser as "dateformat"
func
DateFormat
(
t
time
.
Time
,
layout
string
)
(
datestring
string
)
{
datestring
=
t
.
Format
(
layout
)
return
}
var
DatePatterns
=
[]
string
{
// year
"Y"
,
"2006"
,
// A full numeric representation of a year, 4 digits Examples: 1999 or 2003
"y"
,
"06"
,
//A two digit representation of a year Examples: 99 or 03
// month
"m"
,
"01"
,
// Numeric representation of a month, with leading zeros 01 through 12
"n"
,
"1"
,
// Numeric representation of a month, without leading zeros 1 through 12
"M"
,
"Jan"
,
// A short textual representation of a month, three letters Jan through Dec
"F"
,
"January"
,
// A full textual representation of a month, such as January or March January through December
// day
"d"
,
"02"
,
// Day of the month, 2 digits with leading zeros 01 to 31
"j"
,
"2"
,
// Day of the month without leading zeros 1 to 31
// week
"D"
,
"Mon"
,
// A textual representation of a day, three letters Mon through Sun
"l"
,
"Monday"
,
// A full textual representation of the day of the week Sunday through Saturday
// time
"g"
,
"3"
,
// 12-hour format of an hour without leading zeros 1 through 12
"G"
,
"15"
,
// 24-hour format of an hour without leading zeros 0 through 23
"h"
,
"03"
,
// 12-hour format of an hour with leading zeros 01 through 12
"H"
,
"15"
,
// 24-hour format of an hour with leading zeros 00 through 23
"a"
,
"pm"
,
// Lowercase Ante meridiem and Post meridiem am or pm
"A"
,
"PM"
,
// Uppercase Ante meridiem and Post meridiem AM or PM
"i"
,
"04"
,
// Minutes with leading zeros 00 to 59
"s"
,
"05"
,
// Seconds, with leading zeros 00 through 59
// time zone
"T"
,
"MST"
,
"P"
,
"-07:00"
,
"O"
,
"-0700"
,
// RFC 2822
"r"
,
time
.
RFC1123Z
,
}
// Parse Date use PHP time format
func
DateParse
(
dateString
,
format
string
)
(
time
.
Time
,
error
)
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
time
.
ParseInLocation
(
format
,
dateString
,
time
.
Local
)
}
// Date takes a PHP like date func to Go's time format
func
Date
(
t
time
.
Time
,
format
string
)
string
{
replacer
:=
strings
.
NewReplacer
(
DatePatterns
...
)
format
=
replacer
.
Replace
(
format
)
return
t
.
Format
(
format
)
}
// 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"
func
Compare
(
a
,
b
interface
{})
(
equal
bool
)
{
equal
=
false
if
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
a
))
==
strings
.
TrimSpace
(
fmt
.
Sprintf
(
"%v"
,
b
))
{
equal
=
true
}
return
}
func
Str2html
(
raw
string
)
template
.
HTML
{
return
template
.
HTML
(
raw
)
}
func
Htmlquote
(
src
string
)
string
{
//HTML编码为实体符号
/*
Encodes `text` for raw use in HTML.
>>> htmlquote("<'&\\">")
'<'&">'
*/
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done first!
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"
\"
"
,
"""
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
return
strings
.
TrimSpace
(
text
)
}
func
Htmlunquote
(
src
string
)
string
{
//实体符号解释为HTML
/*
Decodes `text` that's HTML quoted.
>>> htmlunquote('<'&">')
'<\\'&">'
*/
// strings.Replace(s, old, new, n)
// 在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换
text
:=
string
(
src
)
text
=
strings
.
Replace
(
text
,
" "
,
" "
,
-
1
)
text
=
strings
.
Replace
(
text
,
"”"
,
"”"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"“"
,
"“"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"""
,
"
\"
"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"'"
,
"'"
,
-
1
)
text
=
strings
.
Replace
(
text
,
">"
,
">"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"<"
,
"<"
,
-
1
)
text
=
strings
.
Replace
(
text
,
"&"
,
"&"
,
-
1
)
// Must be done last!
return
strings
.
TrimSpace
(
text
)
}
// This will reference the index function local to the current blueprint:
// UrlFor(".index")
// ... print UrlFor("index")
// ... print UrlFor("login")
// ... print UrlFor("login", "next","/"")
// ... print UrlFor("profile", "username","John Doe")
// ...
// /
// /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
func
ParseForm
(
form
url
.
Values
,
obj
interface
{})
error
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
fmt
.
Errorf
(
"%v must be a struct pointer"
,
obj
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
var
tag
string
if
len
(
tags
)
==
0
||
len
(
tags
[
0
])
==
0
{
tag
=
fieldT
.
Name
}
else
if
tags
[
0
]
==
"-"
{
continue
}
else
{
tag
=
tags
[
0
]
}
value
:=
form
.
Get
(
tag
)
if
len
(
value
)
==
0
{
continue
}
switch
fieldT
.
Type
.
Kind
()
{
case
reflect
.
Bool
:
b
,
err
:=
strconv
.
ParseBool
(
value
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetBool
(
b
)
case
reflect
.
Int
,
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
:
x
,
err
:=
strconv
.
ParseInt
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetInt
(
x
)
case
reflect
.
Uint
,
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
:
x
,
err
:=
strconv
.
ParseUint
(
value
,
10
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetUint
(
x
)
case
reflect
.
Float32
,
reflect
.
Float64
:
x
,
err
:=
strconv
.
ParseFloat
(
value
,
64
)
if
err
!=
nil
{
return
err
}
fieldV
.
SetFloat
(
x
)
case
reflect
.
Interface
:
fieldV
.
Set
(
reflect
.
ValueOf
(
value
))
case
reflect
.
String
:
fieldV
.
SetString
(
value
)
}
}
return
nil
}
// form types for RenderForm function
var
FormType
=
map
[
string
]
bool
{
"text"
:
true
,
"textarea"
:
true
,
"hidden"
:
true
,
"password"
:
true
,
}
var
unKind
=
map
[
reflect
.
Kind
]
bool
{
reflect
.
Uintptr
:
true
,
reflect
.
Complex64
:
true
,
reflect
.
Complex128
:
true
,
reflect
.
Array
:
true
,
reflect
.
Chan
:
true
,
reflect
.
Func
:
true
,
reflect
.
Map
:
true
,
reflect
.
Ptr
:
true
,
reflect
.
Slice
:
true
,
reflect
.
Struct
:
true
,
reflect
.
UnsafePointer
:
true
,
}
// obj must be a struct pointer
func
RenderForm
(
obj
interface
{})
template
.
HTML
{
objT
:=
reflect
.
TypeOf
(
obj
)
objV
:=
reflect
.
ValueOf
(
obj
)
if
!
isStructPtr
(
objT
)
{
return
template
.
HTML
(
""
)
}
objT
=
objT
.
Elem
()
objV
=
objV
.
Elem
()
var
raw
[]
string
for
i
:=
0
;
i
<
objT
.
NumField
();
i
++
{
fieldV
:=
objV
.
Field
(
i
)
if
!
fieldV
.
CanSet
()
||
unKind
[
fieldV
.
Kind
()]
{
continue
}
fieldT
:=
objT
.
Field
(
i
)
tags
:=
strings
.
Split
(
fieldT
.
Tag
.
Get
(
"form"
),
","
)
label
:=
fieldT
.
Name
+
": "
name
:=
fieldT
.
Name
fType
:=
"text"
switch
len
(
tags
)
{
case
1
:
if
tags
[
0
]
==
"-"
{
continue
}
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
case
2
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
case
3
:
if
len
(
tags
[
0
])
>
0
{
name
=
tags
[
0
]
}
if
len
(
tags
[
1
])
>
0
{
fType
=
tags
[
1
]
}
if
len
(
tags
[
2
])
>
0
{
label
=
tags
[
2
]
}
}
raw
=
append
(
raw
,
fmt
.
Sprintf
(
`%v<input name="%v" type="%v" value="%v">`
,
label
,
name
,
fType
,
fieldV
.
Interface
()))
}
return
template
.
HTML
(
strings
.
Join
(
raw
,
"</br>"
))
}
func
isStructPtr
(
t
reflect
.
Type
)
bool
{
return
t
.
Kind
()
==
reflect
.
Ptr
&&
t
.
Elem
()
.
Kind
()
==
reflect
.
Struct
}
// 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
utils
_test.go
→
templatefunc
_test.go
View file @
9f2327ee
...
...
@@ -7,18 +7,6 @@ import (
"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
)
{
s
:=
`012345`
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
)
{
type
user
struct
{
Id
int
`form:"-"`
...
...
utils/file.go
View file @
9f2327ee
...
...
@@ -30,7 +30,7 @@ func FileExists(name string) bool {
// search a file in paths.
// this is offen used in search config file in /etc ~/
func
Look
File
(
filename
string
,
paths
...
string
)
(
fullpath
string
,
err
error
)
{
func
Search
File
(
filename
string
,
paths
...
string
)
(
fullpath
string
,
err
error
)
{
for
_
,
path
:=
range
paths
{
if
fullpath
=
filepath
.
Join
(
path
,
filename
);
FileExists
(
fullpath
)
{
return
...
...
@@ -41,7 +41,7 @@ func LookFile(filename string, paths ...string) (fullpath string, err error) {
}
// like command grep -E
// for example: Grep
E
(`^hello`, "hello.txt")
// for example: Grep
File
(`^hello`, "hello.txt")
// \n is striped while read
func
GrepFile
(
patten
string
,
filename
string
)
(
lines
[]
string
,
err
error
)
{
re
,
err
:=
regexp
.
Compile
(
patten
)
...
...
utils/file_test.go
View file @
9f2327ee
...
...
@@ -23,7 +23,7 @@ func TestSelfDir(t *testing.T) {
func
TestFileExists
(
t
*
testing
.
T
)
{
if
!
FileExists
(
"./file.go"
)
{
t
.
Errorf
(
"
/bin/ech
o should exists, but it didn't"
)
t
.
Errorf
(
"
./file.g
o should exists, but it didn't"
)
}
if
FileExists
(
noExistedFile
)
{
...
...
@@ -31,14 +31,14 @@ func TestFileExists(t *testing.T) {
}
}
func
Test
Look
File
(
t
*
testing
.
T
)
{
path
,
err
:=
Look
File
(
filepath
.
Base
(
SelfPath
()),
SelfDir
())
func
Test
Search
File
(
t
*
testing
.
T
)
{
path
,
err
:=
Search
File
(
filepath
.
Base
(
SelfPath
()),
SelfDir
())
if
err
!=
nil
{
t
.
Error
(
err
)
}
t
.
Log
(
path
)
path
,
err
=
Look
File
(
noExistedFile
,
"."
)
path
,
err
=
Search
File
(
noExistedFile
,
"."
)
if
err
==
nil
{
t
.
Errorf
(
"err shouldnot be nil, got path: %s"
,
SelfDir
())
}
...
...
safemap.go
→
utils/
safemap.go
View file @
9f2327ee
package
beego
package
utils
import
(
"sync"
...
...
safemap_test.go
→
utils/
safemap_test.go
View file @
9f2327ee
package
beego
package
utils
import
(
"testing"
...
...
utils/slice.go
0 → 100644
View file @
9f2327ee
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
}
utils/slice_test.go
0 → 100644
View file @
9f2327ee
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"
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment