Compare commits

...

6 Commits

Author SHA1 Message Date
8021f39710 version updates 2020-01-19 21:21:41 +08:00
f2af08270b improve gproc 2020-01-19 20:42:21 +08:00
c2f028848c readme updates 2020-01-18 22:35:07 +08:00
d9c7224861 readme updates 2020-01-18 22:21:37 +08:00
f59a1ada88 improve static service feature, add plugin feature for ghttp.Server 2020-01-17 21:12:52 +08:00
705ab1d33f improve garray; add RemoveValue function for garray 2020-01-17 19:48:50 +08:00
22 changed files with 279 additions and 66 deletions

View File

@ -1,11 +1,10 @@
package main
import (
"fmt"
"github.com/gogf/gf/frame/g"
"os"
)
func main() {
fmt.Println(g.Cfg().FilePath())
g.Cfg().Dump()
g.Dump(os.Args)
}

View File

@ -46,6 +46,10 @@ golang version >= 1.10
`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
# Contributors
This project exists thanks to all the people who contribute. [[Contributors](https://github.com/gogf/gf/graphs/contributors)].
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://opencollective.com/goframe/contributors.svg?width=890&button=false" /></a>
# Donators
We currently accept donation by Alipay/WechatPay, please note your github/gitee account in your payment bill. If you like `GF`, why not [buy developer a cup of coffee](DONATOR.MD)?

View File

@ -55,6 +55,12 @@ golang版本 >= 1.11
`GF` 使用非常友好的 [MIT](LICENSE) 开源协议进行发布,永久`100%`开源免费。
# 贡献
感谢所有参与`GoFrame`开发的贡献者。 [[贡献者列表](https://github.com/gogf/gf/graphs/contributors)].
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://opencollective.com/goframe/contributors.svg?width=890&button=false" /></a>
# 捐赠
如果您喜欢`GF`,要不[给开发者来杯咖啡吧](DONATOR.MD)

View File

@ -176,6 +176,9 @@ func (a *Array) InsertAfter(index int, value interface{}) *Array {
func (a *Array) Remove(index int) interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return nil
}
// Determine array boundaries when deleting to improve deletion efficiency。
if index == 0 {
value := a.array[0]
@ -194,6 +197,16 @@ func (a *Array) Remove(index int) interface{} {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *Array) RemoveValue(value interface{}) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PushLeft pushes one or multiple items to the beginning of array.
func (a *Array) PushLeft(value ...interface{}) *Array {
a.mu.Lock()
@ -418,9 +431,6 @@ func (a *Array) Contains(value interface{}) bool {
// Search searches array by <value>, returns the index of <value>,
// or returns -1 if not exists.
func (a *Array) Search(value interface{}) int {
if len(a.array) == 0 {
return -1
}
a.mu.RLock()
result := -1
for index, v := range a.array {
@ -430,7 +440,20 @@ func (a *Array) Search(value interface{}) int {
}
}
a.mu.RUnlock()
return result
}
func (a *Array) doSearch(value interface{}) int {
if len(a.array) == 0 {
return -1
}
result := -1
for index, v := range a.array {
if v == value {
result = index
break
}
}
return result
}

View File

@ -179,6 +179,9 @@ func (a *IntArray) InsertAfter(index int, value int) *IntArray {
func (a *IntArray) Remove(index int) int {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return 0
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -197,6 +200,16 @@ func (a *IntArray) Remove(index int) int {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *IntArray) RemoveValue(value int) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PushLeft pushes one or multiple items to the beginning of array.
func (a *IntArray) PushLeft(value ...int) *IntArray {
a.mu.Lock()
@ -430,9 +443,6 @@ func (a *IntArray) Contains(value int) bool {
// Search searches array by <value>, returns the index of <value>,
// or returns -1 if not exists.
func (a *IntArray) Search(value int) int {
if len(a.array) == 0 {
return -1
}
a.mu.RLock()
result := -1
for index, v := range a.array {
@ -442,7 +452,6 @@ func (a *IntArray) Search(value int) int {
}
}
a.mu.RUnlock()
return result
}

View File

@ -165,6 +165,9 @@ func (a *StrArray) InsertAfter(index int, value string) *StrArray {
func (a *StrArray) Remove(index int) string {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return ""
}
// Determine array boundaries when deleting to improve deletion efficiency。
if index == 0 {
value := a.array[0]
@ -183,6 +186,16 @@ func (a *StrArray) Remove(index int) string {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *StrArray) RemoveValue(value string) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PushLeft pushes one or multiple items to the beginning of array.
func (a *StrArray) PushLeft(value ...string) *StrArray {
a.mu.Lock()

View File

@ -160,6 +160,9 @@ func (a *SortedArray) Get(index int) interface{} {
func (a *SortedArray) Remove(index int) interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return nil
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -178,6 +181,16 @@ func (a *SortedArray) Remove(index int) interface{} {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *SortedArray) RemoveValue(value interface{}) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PopLeft pops and returns an item from the beginning of array.
func (a *SortedArray) PopLeft() interface{} {
a.mu.Lock()

View File

@ -146,6 +146,9 @@ func (a *SortedIntArray) Get(index int) int {
func (a *SortedIntArray) Remove(index int) int {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return 0
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -164,6 +167,16 @@ func (a *SortedIntArray) Remove(index int) int {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *SortedIntArray) RemoveValue(value int) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PopLeft pops and returns an item from the beginning of array.
func (a *SortedIntArray) PopLeft() int {
a.mu.Lock()

View File

@ -131,6 +131,9 @@ func (a *SortedStrArray) Get(index int) string {
func (a *SortedStrArray) Remove(index int) string {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return ""
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -149,6 +152,16 @@ func (a *SortedStrArray) Remove(index int) string {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *SortedStrArray) RemoveValue(value string) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PopLeft pops and returns an item from the beginning of array.
func (a *SortedStrArray) PopLeft() string {
a.mu.Lock()

View File

@ -34,6 +34,8 @@ func Test_Array_Basic(t *testing.T) {
gtest.Assert(array3.Search(100), -1)
gtest.Assert(array.Contains(100), true)
gtest.Assert(array.Remove(0), 100)
gtest.Assert(array.Remove(-1), nil)
gtest.Assert(array.Remove(100000), nil)
gtest.Assert(array2.Remove(3), 3)
gtest.Assert(array2.Remove(1), 1)
@ -497,3 +499,15 @@ func TestArray_Iterator(t *testing.T) {
gtest.Assert(index, 1)
})
}
func TestArray_RemoveValue(t *testing.T) {
slice := g.Slice{"a", "b", "d", "c"}
array := garray.NewArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
})
}

View File

@ -35,6 +35,8 @@ func Test_IntArray_Basic(t *testing.T) {
gtest.Assert(array2.Search(100), -1)
gtest.Assert(array.Contains(100), true)
gtest.Assert(array.Remove(0), 100)
gtest.Assert(array.Remove(-1), 0)
gtest.Assert(array.Remove(100000), 0)
gtest.Assert(array.Contains(100), false)
array.Append(4)
gtest.Assert(array.Len(), 4)
@ -531,3 +533,16 @@ func TestIntArray_Iterator(t *testing.T) {
gtest.Assert(index, 1)
})
}
func TestIntArray_RemoveValue(t *testing.T) {
slice := g.SliceInt{10, 20, 30, 40}
array := garray.NewIntArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue(99), false)
gtest.Assert(array.RemoveValue(20), true)
gtest.Assert(array.RemoveValue(10), true)
gtest.Assert(array.RemoveValue(20), false)
gtest.Assert(array.RemoveValue(88), false)
gtest.Assert(array.Len(), 2)
})
}

View File

@ -34,6 +34,8 @@ func Test_StrArray_Basic(t *testing.T) {
gtest.Assert(array.Search("100"), 0)
gtest.Assert(array.Contains("100"), true)
gtest.Assert(array.Remove(0), 100)
gtest.Assert(array.Remove(-1), "")
gtest.Assert(array.Remove(100000), "")
gtest.Assert(array.Contains("100"), false)
array.Append("4")
gtest.Assert(array.Len(), 4)
@ -535,3 +537,15 @@ func TestStrArray_Iterator(t *testing.T) {
gtest.Assert(index, 1)
})
}
func TestStrArray_RemoveValue(t *testing.T) {
slice := g.SliceStr{"a", "b", "d", "c"}
array := garray.NewStrArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
})
}

View File

@ -117,6 +117,9 @@ func TestSortedArray_Remove(t *testing.T) {
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Contains("b"), false)
gtest.Assert(array1.Remove(-1), nil)
gtest.Assert(array1.Remove(100000), nil)
i2 := array1.Remove(0)
gtest.Assert(gconv.String(i2), "a")
gtest.Assert(array1.Len(), 2)
@ -634,3 +637,15 @@ func TestSortedArray_Iterator(t *testing.T) {
gtest.Assert(index, 1)
})
}
func TestSortedArray_RemoveValue(t *testing.T) {
slice := g.Slice{"a", "b", "d", "c"}
array := garray.NewSortedArrayFrom(slice, gutil.ComparatorString)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
})
}

View File

@ -78,6 +78,10 @@ func TestSortedIntArray_Remove(t *testing.T) {
gtest.Case(t, func() {
a1 := []int{1, 3, 5, 0}
array1 := garray.NewSortedIntArrayFrom(a1)
gtest.Assert(array1.Remove(-1), 0)
gtest.Assert(array1.Remove(100000), 0)
i1 := array1.Remove(2)
gtest.Assert(i1, 3)
gtest.Assert(array1.Search(5), 2)
@ -513,3 +517,16 @@ func TestSortedIntArray_Iterator(t *testing.T) {
gtest.Assert(index, 1)
})
}
func TestSortedIntArray_RemoveValue(t *testing.T) {
slice := g.SliceInt{10, 20, 30, 40}
array := garray.NewSortedIntArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue(99), false)
gtest.Assert(array.RemoveValue(20), true)
gtest.Assert(array.RemoveValue(10), true)
gtest.Assert(array.RemoveValue(20), false)
gtest.Assert(array.RemoveValue(88), false)
gtest.Assert(array.Len(), 2)
})
}

View File

@ -77,6 +77,10 @@ func TestSortedStrArray_Remove(t *testing.T) {
gtest.Case(t, func() {
a1 := []string{"a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1.Remove(-1), "")
gtest.Assert(array1.Remove(100000), "")
gtest.Assert(array1.Remove(2), "c")
gtest.Assert(array1.Get(2), "d")
gtest.Assert(array1.Len(), 3)
@ -523,3 +527,15 @@ func TestSortedStrArray_Iterator(t *testing.T) {
gtest.Assert(index, 1)
})
}
func TestSortedStrArray_RemoveValue(t *testing.T) {
slice := g.SliceStr{"a", "b", "d", "c"}
array := garray.NewSortedStrArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
})
}

View File

@ -8,6 +8,7 @@ package ghttp
import (
"fmt"
"github.com/gogf/gf/os/gres"
"github.com/gogf/gf/os/gview"
"net/http"
"strings"
@ -29,6 +30,7 @@ type Request struct {
EnterTime int64 // Request starting time in microseconds.
LeaveTime int64 // Request ending time in microseconds.
Middleware *Middleware // The middleware manager.
StaticFile *StaticFile // Static file object when static file serving.
handlers []*handlerParsedItem // All matched handlers containing handler, hook and middleware for this request .
hasHookHandler bool // A bool marking whether there's hook handler in the handlers for performance purpose.
hasServeHandler bool // A bool marking whether there's serving handler in the handlers for performance purpose.
@ -50,13 +52,20 @@ type Request struct {
viewParams gview.Params // Custom template view variables for this response.
}
// StaticFile is the file struct for static file service.
type StaticFile struct {
File *gres.File // Resource file object.
Path string // File path.
IsDir bool // Is directory.
}
// newRequest creates and returns a new request object.
func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request {
request := &Request{
Server: s,
Request: r,
Response: newResponse(s, w),
EnterTime: gtime.Microsecond(),
EnterTime: gtime.TimestampMicro(),
}
request.Cookie = GetCookie(request)
request.Session = s.sessionManager.New(request.GetSessionId())

View File

@ -41,11 +41,11 @@ func newResponse(s *Server, w http.ResponseWriter) *Response {
// ServeFile serves the file to the response.
func (r *Response) ServeFile(path string, allowIndex ...bool) {
serveFile := (*staticServeFile)(nil)
serveFile := (*StaticFile)(nil)
if file := gres.Get(path); file != nil {
serveFile = &staticServeFile{
file: file,
dir: file.FileInfo().IsDir(),
serveFile = &StaticFile{
File: file,
IsDir: file.FileInfo().IsDir(),
}
} else {
path = gfile.RealPath(path)
@ -53,22 +53,22 @@ func (r *Response) ServeFile(path string, allowIndex ...bool) {
r.WriteStatus(http.StatusNotFound)
return
}
serveFile = &staticServeFile{path: path}
serveFile = &StaticFile{Path: path}
}
r.Server.serveFile(r.Request, serveFile, allowIndex...)
}
// ServeFileDownload serves file downloading to the response.
func (r *Response) ServeFileDownload(path string, name ...string) {
serveFile := (*staticServeFile)(nil)
serveFile := (*StaticFile)(nil)
downloadName := ""
if len(name) > 0 {
downloadName = name[0]
}
if file := gres.Get(path); file != nil {
serveFile = &staticServeFile{
file: file,
dir: file.FileInfo().IsDir(),
serveFile = &StaticFile{
File: file,
IsDir: file.FileInfo().IsDir(),
}
if downloadName == "" {
downloadName = gfile.Basename(file.Name())
@ -79,7 +79,7 @@ func (r *Response) ServeFileDownload(path string, name ...string) {
r.WriteStatus(http.StatusNotFound)
return
}
serveFile = &staticServeFile{path: path}
serveFile = &StaticFile{Path: path}
if downloadName == "" {
downloadName = gfile.Basename(path)
}

View File

@ -24,13 +24,6 @@ import (
"github.com/gogf/gf/os/gtime"
)
// staticServeFile is the file struct for static service.
type staticServeFile struct {
file *gres.File // Resource file object.
path string // File path.
dir bool // Is directory.
}
// 默认HTTP Server处理入口http包底层默认使用了gorutine异步处理请求所以这里不再异步执行
func (s *Server) defaultHandler(w http.ResponseWriter, r *http.Request) {
s.handleRequest(w, r)
@ -65,7 +58,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
defer func() {
// 设置请求完成时间
request.LeaveTime = gtime.Microsecond()
request.LeaveTime = gtime.TimestampMicro()
// error log
if request.error != nil {
s.handleErrorLog(request.error, request)
@ -86,11 +79,10 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
// 静态文件 > 动态服务 > 静态目录
// ============================================================
serveFile := (*staticServeFile)(nil)
// 优先执行静态文件检索(检测是否存在对应的静态文件包括index files处理)
if s.config.FileServerEnabled {
serveFile = s.searchStaticFile(r.URL.Path)
if serveFile != nil {
request.StaticFile = s.searchStaticFile(r.URL.Path)
if request.StaticFile != nil {
request.isFileRequest = true
}
}
@ -99,7 +91,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
request.handlers, request.hasHookHandler, request.hasServeHandler = s.getHandlersWithCache(request)
// 判断最终对该请求提供的服务方式
if serveFile != nil && serveFile.dir && request.hasServeHandler {
if request.StaticFile != nil && request.StaticFile.IsDir && request.hasServeHandler {
request.isFileRequest = false
}
@ -110,15 +102,15 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
if !request.IsExited() {
if request.isFileRequest {
// 静态服务
s.serveFile(request, serveFile)
s.serveFile(request, request.StaticFile)
} else {
if len(request.handlers) > 0 {
// 动态服务
request.Middleware.Next()
} else {
if serveFile != nil && serveFile.dir {
if request.StaticFile != nil && request.StaticFile.IsDir {
// 静态目录
s.serveFile(request, serveFile)
s.serveFile(request, request.StaticFile)
} else {
if len(request.Response.Header()) == 0 &&
request.Response.Status == 0 &&
@ -142,7 +134,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
// HTTP status checking.
if request.Response.Status == 0 {
if serveFile != nil || request.Middleware.served || request.Response.buffer.Len() > 0 {
if request.StaticFile != nil || request.Middleware.served || request.Response.buffer.Len() > 0 {
request.Response.WriteHeader(http.StatusOK)
} else {
request.Response.WriteHeader(http.StatusNotFound)
@ -174,7 +166,7 @@ func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) {
// searchStaticFile searches the file with given URI.
// It returns a file struct specifying the file information.
func (s *Server) searchStaticFile(uri string) *staticServeFile {
func (s *Server) searchStaticFile(uri string) *StaticFile {
var file *gres.File
var path string
var dir bool
@ -188,16 +180,16 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
}
file = gres.GetWithIndex(item.path+uri[len(item.prefix):], s.config.IndexFiles)
if file != nil {
return &staticServeFile{
file: file,
dir: file.FileInfo().IsDir(),
return &StaticFile{
File: file,
IsDir: file.FileInfo().IsDir(),
}
}
path, dir = gspath.Search(item.path, uri[len(item.prefix):], s.config.IndexFiles...)
if path != "" {
return &staticServeFile{
path: path,
dir: dir,
return &StaticFile{
Path: path,
IsDir: dir,
}
}
@ -209,15 +201,15 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
for _, p := range s.config.SearchPaths {
file = gres.GetWithIndex(p+uri, s.config.IndexFiles)
if file != nil {
return &staticServeFile{
file: file,
dir: file.FileInfo().IsDir(),
return &StaticFile{
File: file,
IsDir: file.FileInfo().IsDir(),
}
}
if path, dir = gspath.Search(p, uri, s.config.IndexFiles...); path != "" {
return &staticServeFile{
path: path,
dir: dir,
return &StaticFile{
Path: path,
IsDir: dir,
}
}
}
@ -225,9 +217,9 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
// Lastly search the resource manager.
if len(s.config.StaticPaths) == 0 && len(s.config.SearchPaths) == 0 {
if file = gres.GetWithIndex(uri, s.config.IndexFiles); file != nil {
return &staticServeFile{
file: file,
dir: file.FileInfo().IsDir(),
return &StaticFile{
File: file,
IsDir: file.FileInfo().IsDir(),
}
}
}
@ -235,24 +227,24 @@ func (s *Server) searchStaticFile(uri string) *staticServeFile {
}
// http server静态文件处理path可以为相对路径也可以为绝对路径
func (s *Server) serveFile(r *Request, f *staticServeFile, allowIndex ...bool) {
func (s *Server) serveFile(r *Request, f *StaticFile, allowIndex ...bool) {
// 使用资源文件
if f.file != nil {
if f.dir {
if f.File != nil {
if f.IsDir {
if s.config.IndexFolder || (len(allowIndex) > 0 && allowIndex[0]) {
s.listDir(r, f.file)
s.listDir(r, f.File)
} else {
r.Response.WriteStatus(http.StatusForbidden)
}
} else {
info := f.file.FileInfo()
info := f.File.FileInfo()
r.Response.wroteHeader = true
http.ServeContent(r.Response.Writer.RawWriter(), r.Request, info.Name(), info.ModTime(), f.file)
http.ServeContent(r.Response.Writer.RawWriter(), r.Request, info.Name(), info.ModTime(), f.File)
}
return
}
// 使用磁盘文件
file, err := os.Open(f.path)
file, err := os.Open(f.Path)
if err != nil {
r.Response.WriteStatus(http.StatusForbidden)
return

View File

@ -0,0 +1,24 @@
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package ghttp
import "github.com/gogf/gf/os/glog"
// Plugin is the interface for server plugin.
type Plugin interface {
Install(s *Server) error
Remove() error
}
// Plugin adds plugin for server.
func (s *Server) Plugin(plugin ...Plugin) {
for _, p := range plugin {
if err := p.Install(s); err != nil {
glog.Fatal(err)
}
}
}

View File

@ -189,6 +189,11 @@ func SearchBinary(file string) string {
if gfile.Exists(file) {
return file
}
return SearchBinaryPath(file)
}
// SearchBinaryPath searches the binary <file> in PATH environment.
func SearchBinaryPath(file string) string {
array := ([]string)(nil)
switch runtime.GOOS {
case "windows":

View File

@ -24,12 +24,11 @@ type Process struct {
// NewProcess creates and returns a new Process.
func NewProcess(path string, args []string, environment ...[]string) *Process {
var env []string
env := os.Environ()
if len(environment) > 0 {
env = make([]string, len(environment[0]))
copy(env, environment[0])
} else {
env = os.Environ()
for k, v := range environment[0] {
env[k] = v
}
}
process := &Process{
Manager: nil,

View File

@ -1,4 +1,4 @@
package gf
const VERSION = "v1.11.3"
const VERSION = "v1.11.4"
const AUTHORS = "john<john@goframe.org>"