1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-22 18:00:55 +00:00

Merge pull request #404 from fuxiaohei/master

add comments in cache package
This commit is contained in:
astaxie 2013-12-21 23:28:43 -08:00
commit e858f903a3
9 changed files with 114 additions and 19 deletions

22
cache/cache.go vendored
View File

@ -4,14 +4,32 @@ import (
"fmt" "fmt"
) )
// Cache interface contains all behaviors for cache adapter.
// usage:
// cache.Register("file",cache.NewFileCache()) // this operation is run in init method of file.go.
// c := cache.NewCache("file","{....}")
// c.Put("key",value,3600)
// v := c.Get("key")
//
// c.Incr("counter") // now is 1
// c.Incr("counter") // now is 2
// count := c.Get("counter").(int)
type Cache interface { type Cache interface {
// get cached value by key.
Get(key string) interface{} Get(key string) interface{}
// set cached value with key and expire time.
Put(key string, val interface{}, timeout int64) error Put(key string, val interface{}, timeout int64) error
// delete cached value by key.
Delete(key string) error Delete(key string) error
// increase cached int value by key, as a counter.
Incr(key string) error Incr(key string) error
// decrease cached int value by key, as a counter.
Decr(key string) error Decr(key string) error
// check cached value is existed or not.
IsExist(key string) bool IsExist(key string) bool
// clear all cache.
ClearAll() error ClearAll() error
// start gc routine via config string setting.
StartAndGC(config string) error StartAndGC(config string) error
} }
@ -30,7 +48,9 @@ func Register(name string, adapter Cache) {
adapters[name] = adapter adapters[name] = adapter
} }
// config need to be correct JSON as string: {"interval":360} // Create a new cache driver by adapter and config string.
// config need to be correct JSON as string: {"interval":360}.
// it will start gc automatically.
func NewCache(adapterName, config string) (Cache, error) { func NewCache(adapterName, config string) (Cache, error) {
adapter, ok := adapters[adapterName] adapter, ok := adapters[adapterName]
if !ok { if !ok {

6
cache/conv.go vendored
View File

@ -5,6 +5,7 @@ import (
"strconv" "strconv"
) )
// convert interface to string.
func GetString(v interface{}) string { func GetString(v interface{}) string {
switch result := v.(type) { switch result := v.(type) {
case string: case string:
@ -20,6 +21,7 @@ func GetString(v interface{}) string {
} }
} }
// convert interface to int.
func GetInt(v interface{}) int { func GetInt(v interface{}) int {
switch result := v.(type) { switch result := v.(type) {
case int: case int:
@ -40,6 +42,7 @@ func GetInt(v interface{}) int {
return 0 return 0
} }
// convert interface to int64.
func GetInt64(v interface{}) int64 { func GetInt64(v interface{}) int64 {
switch result := v.(type) { switch result := v.(type) {
case int: case int:
@ -60,6 +63,7 @@ func GetInt64(v interface{}) int64 {
return 0 return 0
} }
// convert interface to float64.
func GetFloat64(v interface{}) float64 { func GetFloat64(v interface{}) float64 {
switch result := v.(type) { switch result := v.(type) {
case float64: case float64:
@ -76,6 +80,7 @@ func GetFloat64(v interface{}) float64 {
return 0 return 0
} }
// convert interface to bool.
func GetBool(v interface{}) bool { func GetBool(v interface{}) bool {
switch result := v.(type) { switch result := v.(type) {
case bool: case bool:
@ -92,6 +97,7 @@ func GetBool(v interface{}) bool {
return false return false
} }
// convert interface to byte slice.
func getByteArray(v interface{}) []byte { func getByteArray(v interface{}) []byte {
switch result := v.(type) { switch result := v.(type) {
case []byte: case []byte:

44
cache/file.go vendored
View File

@ -24,6 +24,8 @@ func init() {
Register("file", NewFileCache()) Register("file", NewFileCache())
} }
// FileCacheItem is basic unit of file cache adapter.
// it contains data and expire time.
type FileCacheItem struct { type FileCacheItem struct {
Data interface{} Data interface{}
Lastaccess int64 Lastaccess int64
@ -31,15 +33,13 @@ type FileCacheItem struct {
} }
var ( var (
FileCachePath string = "cache" FileCachePath string = "cache" // cache directory
FileCacheFileSuffix string = ".bin" FileCacheFileSuffix string = ".bin" // cache file suffix
FileCacheDirectoryLevel int = 2 FileCacheDirectoryLevel int = 2 // cache file deep level if auto generated cache files.
/** FileCacheEmbedExpiry int64 = 0 // cache expire time, default is no expire forever.
* 默认永不过期
*/
FileCacheEmbedExpiry int64 = 0
) )
// FileCache is cache adapter for file storage.
type FileCache struct { type FileCache struct {
CachePath string CachePath string
FileSuffix string FileSuffix string
@ -47,11 +47,14 @@ type FileCache struct {
EmbedExpiry int EmbedExpiry int
} }
// Create new file cache with default directory and suffix.
// the level and expiry need set in method StartAndGC as config string.
func NewFileCache() *FileCache { func NewFileCache() *FileCache {
// return &FileCache{CachePath:FileCachePath, FileSuffix:FileCacheFileSuffix} return &FileCache{CachePath:FileCachePath, FileSuffix:FileCacheFileSuffix}
return &FileCache{}
} }
// Start and begin gc for file cache.
// the config need to be like {CachePath:"/cache","FileSuffix":".bin","DirectoryLevel":2,"EmbedExpiry":0}
func (this *FileCache) StartAndGC(config string) error { func (this *FileCache) StartAndGC(config string) error {
var cfg map[string]string var cfg map[string]string
@ -78,6 +81,7 @@ func (this *FileCache) StartAndGC(config string) error {
return nil return nil
} }
// Init will make new dir for file cache if not exist.
func (this *FileCache) Init() { func (this *FileCache) Init() {
app := filepath.Dir(os.Args[0]) app := filepath.Dir(os.Args[0])
this.CachePath = filepath.Join(app, this.CachePath) this.CachePath = filepath.Join(app, this.CachePath)
@ -93,6 +97,7 @@ func (this *FileCache) Init() {
//fmt.Println(this.getCacheFileName("123456")); //fmt.Println(this.getCacheFileName("123456"));
} }
// get cached file name. it's md5 encoded.
func (this *FileCache) getCacheFileName(key string) string { func (this *FileCache) getCacheFileName(key string) string {
m := md5.New() m := md5.New()
io.WriteString(m, key) io.WriteString(m, key)
@ -119,6 +124,8 @@ func (this *FileCache) getCacheFileName(key string) string {
return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, this.FileSuffix)) return filepath.Join(cachePath, fmt.Sprintf("%s%s", keyMd5, this.FileSuffix))
} }
// Get value from file cache.
// if non-exist or expired, return empty string.
func (this *FileCache) Get(key string) interface{} { func (this *FileCache) Get(key string) interface{} {
filename := this.getCacheFileName(key) filename := this.getCacheFileName(key)
filedata, err := File_get_contents(filename) filedata, err := File_get_contents(filename)
@ -134,6 +141,8 @@ func (this *FileCache) Get(key string) interface{} {
return to.Data return to.Data
} }
// Put value into file cache.
// timeout means how long to keep this file, unit of second.
func (this *FileCache) Put(key string, val interface{}, timeout int64) error { func (this *FileCache) Put(key string, val interface{}, timeout int64) error {
filename := this.getCacheFileName(key) filename := this.getCacheFileName(key)
var item FileCacheItem var item FileCacheItem
@ -152,6 +161,7 @@ func (this *FileCache) Put(key string, val interface{}, timeout int64) error {
return err return err
} }
// Delete file cache value.
func (this *FileCache) Delete(key string) error { func (this *FileCache) Delete(key string) error {
filename := this.getCacheFileName(key) filename := this.getCacheFileName(key)
if ok, _ := exists(filename); ok { if ok, _ := exists(filename); ok {
@ -160,6 +170,8 @@ func (this *FileCache) Delete(key string) error {
return nil return nil
} }
// Increase cached int value.
// this value is saving forever unless Delete.
func (this *FileCache) Incr(key string) error { func (this *FileCache) Incr(key string) error {
data := this.Get(key) data := this.Get(key)
var incr int var incr int
@ -173,6 +185,7 @@ func (this *FileCache) Incr(key string) error {
return nil return nil
} }
// Decrease cached int value.
func (this *FileCache) Decr(key string) error { func (this *FileCache) Decr(key string) error {
data := this.Get(key) data := this.Get(key)
var decr int var decr int
@ -185,18 +198,22 @@ func (this *FileCache) Decr(key string) error {
return nil return nil
} }
// Check value is exist.
func (this *FileCache) IsExist(key string) bool { func (this *FileCache) IsExist(key string) bool {
filename := this.getCacheFileName(key) filename := this.getCacheFileName(key)
ret, _ := exists(filename) ret, _ := exists(filename)
return ret return ret
} }
// Clean cached files.
// not implemented.
func (this *FileCache) ClearAll() error { func (this *FileCache) ClearAll() error {
//this.CachePath .递归删除 //this.CachePath .递归删除
return nil return nil
} }
// check file exist.
func exists(path string) (bool, error) { func exists(path string) (bool, error) {
_, err := os.Stat(path) _, err := os.Stat(path)
if err == nil { if err == nil {
@ -208,7 +225,9 @@ func exists(path string) (bool, error) {
return false, err return false, err
} }
func File_get_contents(filename string) ([]byte, error) { //文件不存在时自动创建 // Get bytes to file.
// if non-exist, create this file.
func File_get_contents(filename string) ([]byte, error) {
f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm) f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil { if err != nil {
return []byte(""), err return []byte(""), err
@ -226,6 +245,8 @@ func File_get_contents(filename string) ([]byte, error) { //文件不存在时
return []byte(""), err return []byte(""), err
} }
// Put bytes to file.
// if non-exist, create this file.
func File_put_contents(filename string, content []byte) error { func File_put_contents(filename string, content []byte) error {
fp, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm) fp, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
if err != nil { if err != nil {
@ -235,6 +256,8 @@ func File_put_contents(filename string, content []byte) error {
_, err = fp.Write(content) _, err = fp.Write(content)
return err return err
} }
// Gob encodes file cache item.
func Gob_encode(data interface{}) ([]byte, error) { func Gob_encode(data interface{}) ([]byte, error) {
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
enc := gob.NewEncoder(buf) enc := gob.NewEncoder(buf)
@ -245,6 +268,7 @@ func Gob_encode(data interface{}) ([]byte, error) {
return buf.Bytes(), err return buf.Bytes(), err
} }
// Gob decodes file cache item.
func Gob_decode(data []byte, to interface{}) error { func Gob_decode(data []byte, to interface{}) error {
buf := bytes.NewBuffer(data) buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf) dec := gob.NewDecoder(buf)

15
cache/memcache.go vendored
View File

@ -7,15 +7,18 @@ import (
"github.com/beego/memcache" "github.com/beego/memcache"
) )
// Memcache adapter.
type MemcacheCache struct { type MemcacheCache struct {
c *memcache.Connection c *memcache.Connection
conninfo string conninfo string
} }
// create new memcache adapter.
func NewMemCache() *MemcacheCache { func NewMemCache() *MemcacheCache {
return &MemcacheCache{} return &MemcacheCache{}
} }
// get value from memcache.
func (rc *MemcacheCache) Get(key string) interface{} { func (rc *MemcacheCache) Get(key string) interface{} {
if rc.c == nil { if rc.c == nil {
rc.c = rc.connectInit() rc.c = rc.connectInit()
@ -33,6 +36,7 @@ func (rc *MemcacheCache) Get(key string) interface{} {
return contain return contain
} }
// put value to memcache. only support string.
func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error { func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
if rc.c == nil { if rc.c == nil {
rc.c = rc.connectInit() rc.c = rc.connectInit()
@ -48,6 +52,7 @@ func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
return err return err
} }
// delete value in memcache.
func (rc *MemcacheCache) Delete(key string) error { func (rc *MemcacheCache) Delete(key string) error {
if rc.c == nil { if rc.c == nil {
rc.c = rc.connectInit() rc.c = rc.connectInit()
@ -56,14 +61,19 @@ func (rc *MemcacheCache) Delete(key string) error {
return err return err
} }
// [Not Support]
// increase counter.
func (rc *MemcacheCache) Incr(key string) error { func (rc *MemcacheCache) Incr(key string) error {
return errors.New("not support in memcache") return errors.New("not support in memcache")
} }
// [Not Support]
// decrease counter.
func (rc *MemcacheCache) Decr(key string) error { func (rc *MemcacheCache) Decr(key string) error {
return errors.New("not support in memcache") return errors.New("not support in memcache")
} }
// check value exists in memcache.
func (rc *MemcacheCache) IsExist(key string) bool { func (rc *MemcacheCache) IsExist(key string) bool {
if rc.c == nil { if rc.c == nil {
rc.c = rc.connectInit() rc.c = rc.connectInit()
@ -80,6 +90,7 @@ func (rc *MemcacheCache) IsExist(key string) bool {
return true return true
} }
// clear all cached in memcache.
func (rc *MemcacheCache) ClearAll() error { func (rc *MemcacheCache) ClearAll() error {
if rc.c == nil { if rc.c == nil {
rc.c = rc.connectInit() rc.c = rc.connectInit()
@ -88,6 +99,9 @@ func (rc *MemcacheCache) ClearAll() error {
return err return err
} }
// start memcache adapter.
// config string is like {"conn":"connection info"}.
// if connecting error, return.
func (rc *MemcacheCache) StartAndGC(config string) error { func (rc *MemcacheCache) StartAndGC(config string) error {
var cf map[string]string var cf map[string]string
json.Unmarshal([]byte(config), &cf) json.Unmarshal([]byte(config), &cf)
@ -102,6 +116,7 @@ func (rc *MemcacheCache) StartAndGC(config string) error {
return nil return nil
} }
// connect to memcache and keep the connection.
func (rc *MemcacheCache) connectInit() *memcache.Connection { func (rc *MemcacheCache) connectInit() *memcache.Connection {
c, err := memcache.Connect(rc.conninfo) c, err := memcache.Connect(rc.conninfo)
if err != nil { if err != nil {

20
cache/memory.go vendored
View File

@ -9,28 +9,34 @@ import (
) )
var ( var (
// clock time of recycling the expired cache items in memory.
DefaultEvery int = 60 // 1 minute DefaultEvery int = 60 // 1 minute
) )
// Memory cache item.
type MemoryItem struct { type MemoryItem struct {
val interface{} val interface{}
Lastaccess time.Time Lastaccess time.Time
expired int64 expired int64
} }
// Memory cache adapter.
// it contains a RW locker for safe map storage.
type MemoryCache struct { type MemoryCache struct {
lock sync.RWMutex lock sync.RWMutex
dur time.Duration dur time.Duration
items map[string]*MemoryItem items map[string]*MemoryItem
Every int // Run an expiration check Every seconds Every int // run an expiration check Every cloc; time
} }
// NewDefaultCache returns a new FileCache with sane defaults. // NewMemoryCache returns a new MemoryCache.
func NewMemoryCache() *MemoryCache { func NewMemoryCache() *MemoryCache {
cache := MemoryCache{items: make(map[string]*MemoryItem)} cache := MemoryCache{items: make(map[string]*MemoryItem)}
return &cache return &cache
} }
// Get cache from memory.
// if non-existed or expired, return nil.
func (bc *MemoryCache) Get(name string) interface{} { func (bc *MemoryCache) Get(name string) interface{} {
bc.lock.RLock() bc.lock.RLock()
defer bc.lock.RUnlock() defer bc.lock.RUnlock()
@ -45,6 +51,7 @@ func (bc *MemoryCache) Get(name string) interface{} {
return itm.val return itm.val
} }
// Put cache to memory.
func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error { func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error {
bc.lock.Lock() bc.lock.Lock()
defer bc.lock.Unlock() defer bc.lock.Unlock()
@ -57,6 +64,7 @@ func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error
return nil return nil
} }
/// Delete cache in memory.
func (bc *MemoryCache) Delete(name string) error { func (bc *MemoryCache) Delete(name string) error {
bc.lock.Lock() bc.lock.Lock()
defer bc.lock.Unlock() defer bc.lock.Unlock()
@ -71,6 +79,8 @@ func (bc *MemoryCache) Delete(name string) error {
return nil return nil
} }
// Increase cache counter in memory.
// it supports int,int64,int32,uint,uint64,uint32.
func (bc *MemoryCache) Incr(key string) error { func (bc *MemoryCache) Incr(key string) error {
bc.lock.RLock() bc.lock.RLock()
defer bc.lock.RUnlock() defer bc.lock.RUnlock()
@ -97,6 +107,7 @@ func (bc *MemoryCache) Incr(key string) error {
return nil return nil
} }
// Decrease counter in memory.
func (bc *MemoryCache) Decr(key string) error { func (bc *MemoryCache) Decr(key string) error {
bc.lock.RLock() bc.lock.RLock()
defer bc.lock.RUnlock() defer bc.lock.RUnlock()
@ -135,6 +146,7 @@ func (bc *MemoryCache) Decr(key string) error {
return nil return nil
} }
// check cache exist in memory.
func (bc *MemoryCache) IsExist(name string) bool { func (bc *MemoryCache) IsExist(name string) bool {
bc.lock.RLock() bc.lock.RLock()
defer bc.lock.RUnlock() defer bc.lock.RUnlock()
@ -142,6 +154,7 @@ func (bc *MemoryCache) IsExist(name string) bool {
return ok return ok
} }
// delete all cache in memory.
func (bc *MemoryCache) ClearAll() error { func (bc *MemoryCache) ClearAll() error {
bc.lock.Lock() bc.lock.Lock()
defer bc.lock.Unlock() defer bc.lock.Unlock()
@ -149,7 +162,7 @@ func (bc *MemoryCache) ClearAll() error {
return nil return nil
} }
// Start activates the file cache; it will // start memory cache. it will check expiration in every clock time.
func (bc *MemoryCache) StartAndGC(config string) error { func (bc *MemoryCache) StartAndGC(config string) error {
var cf map[string]int var cf map[string]int
json.Unmarshal([]byte(config), &cf) json.Unmarshal([]byte(config), &cf)
@ -167,6 +180,7 @@ func (bc *MemoryCache) StartAndGC(config string) error {
return nil return nil
} }
// check expiration.
func (bc *MemoryCache) vaccuum() { func (bc *MemoryCache) vaccuum() {
if bc.Every < 1 { if bc.Every < 1 {
return return

16
cache/redis.go vendored
View File

@ -8,19 +8,23 @@ import (
) )
var ( var (
// the collection name of redis for cache adapter.
DefaultKey string = "beecacheRedis" DefaultKey string = "beecacheRedis"
) )
// Redis cache adapter.
type RedisCache struct { type RedisCache struct {
c redis.Conn c redis.Conn
conninfo string conninfo string
key string key string
} }
// create new redis cache with default collection name.
func NewRedisCache() *RedisCache { func NewRedisCache() *RedisCache {
return &RedisCache{key: DefaultKey} return &RedisCache{key: DefaultKey}
} }
// Get cache from redis.
func (rc *RedisCache) Get(key string) interface{} { func (rc *RedisCache) Get(key string) interface{} {
if rc.c == nil { if rc.c == nil {
var err error var err error
@ -36,6 +40,8 @@ func (rc *RedisCache) Get(key string) interface{} {
return v return v
} }
// put cache to redis.
// timeout is ignored.
func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error { func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
if rc.c == nil { if rc.c == nil {
var err error var err error
@ -48,6 +54,7 @@ func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
return err return err
} }
// delete cache in redis.
func (rc *RedisCache) Delete(key string) error { func (rc *RedisCache) Delete(key string) error {
if rc.c == nil { if rc.c == nil {
var err error var err error
@ -60,6 +67,7 @@ func (rc *RedisCache) Delete(key string) error {
return err return err
} }
// check cache exist in redis.
func (rc *RedisCache) IsExist(key string) bool { func (rc *RedisCache) IsExist(key string) bool {
if rc.c == nil { if rc.c == nil {
var err error var err error
@ -75,6 +83,7 @@ func (rc *RedisCache) IsExist(key string) bool {
return v return v
} }
// increase counter in redis.
func (rc *RedisCache) Incr(key string) error { func (rc *RedisCache) Incr(key string) error {
if rc.c == nil { if rc.c == nil {
var err error var err error
@ -90,6 +99,7 @@ func (rc *RedisCache) Incr(key string) error {
return nil return nil
} }
// decrease counter in redis.
func (rc *RedisCache) Decr(key string) error { func (rc *RedisCache) Decr(key string) error {
if rc.c == nil { if rc.c == nil {
var err error var err error
@ -105,6 +115,7 @@ func (rc *RedisCache) Decr(key string) error {
return nil return nil
} }
// clean all cache in redis. delete this redis collection.
func (rc *RedisCache) ClearAll() error { func (rc *RedisCache) ClearAll() error {
if rc.c == nil { if rc.c == nil {
var err error var err error
@ -117,6 +128,10 @@ func (rc *RedisCache) ClearAll() error {
return err return err
} }
// start redis cache adapter.
// config is like {"key":"collection key","conn":"connection info"}
// the cache item in redis are stored forever,
// so no gc operation.
func (rc *RedisCache) StartAndGC(config string) error { func (rc *RedisCache) StartAndGC(config string) error {
var cf map[string]string var cf map[string]string
json.Unmarshal([]byte(config), &cf) json.Unmarshal([]byte(config), &cf)
@ -139,6 +154,7 @@ func (rc *RedisCache) StartAndGC(config string) error {
return nil return nil
} }
// connect to redis.
func (rc *RedisCache) connectInit() (redis.Conn, error) { func (rc *RedisCache) connectInit() (redis.Conn, error) {
c, err := redis.Dial("tcp", rc.conninfo) c, err := redis.Dial("tcp", rc.conninfo)
if err != nil { if err != nil {

View File

@ -241,7 +241,7 @@ func (c *Controller) ServeJson(encoding ...bool) {
c.Ctx.Output.Json(c.Data["json"], hasIndent, hasencoding) c.Ctx.Output.Json(c.Data["json"], hasIndent, hasencoding)
} }
// ServeJson sends a jsonp response. // ServeJsonp sends a jsonp response.
func (c *Controller) ServeJsonp() { func (c *Controller) ServeJsonp() {
var hasIndent bool var hasIndent bool
if RunMode == "prod" { if RunMode == "prod" {
@ -252,7 +252,7 @@ func (c *Controller) ServeJsonp() {
c.Ctx.Output.Jsonp(c.Data["jsonp"], hasIndent) c.Ctx.Output.Jsonp(c.Data["jsonp"], hasIndent)
} }
// ServeJson sends xml response. // ServeXml sends xml response.
func (c *Controller) ServeXml() { func (c *Controller) ServeXml() {
var hasIndent bool var hasIndent bool
if RunMode == "prod" { if RunMode == "prod" {

View File

@ -17,7 +17,7 @@ import (
var ( var (
beegoTplFuncMap template.FuncMap beegoTplFuncMap template.FuncMap
// beego template caching map ans supported template file extensions. // beego template caching map and supported template file extensions.
BeeTemplates map[string]*template.Template BeeTemplates map[string]*template.Template
BeeTemplateExt []string BeeTemplateExt []string
) )
@ -89,7 +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. // return this path contains 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) {

View File

@ -203,7 +203,7 @@ func AssetsJs(src string) template.HTML {
return template.HTML(text) return template.HTML(text)
} }
// returns stylesheet link tag with str string. // returns stylesheet link tag with src string.
func AssetsCss(src string) template.HTML { func AssetsCss(src string) template.HTML {
text := string(src) text := string(src)