用go 重写php 常用的内置函数(php2go)
地址:https://github.com/syyongx/php2go,点击下载
// php2go functions package php2go import ( "archive/zip" "bytes" "crypto/md5" "crypto/sha1" "encoding/base64" "encoding/binary" "encoding/csv" "encoding/hex" "encoding/json" "fmt" "hash/crc32" "html" "io" "io/ioutil" "math" "math/rand" "net" "net/url" "os" "os/exec" "path/filepath" "reflect" "runtime" "strconv" "strings" "syscall" "time" "unicode" "unicode/utf8" ) //////////// Date/Time Functions //////////// // Time time() func Time() int64 { return time.Now().Unix() } // Strtotime strtotime() // Strtotime("02/01/2006 15:04:05", "02/01/2016 15:04:05") == 1451747045 // Strtotime("3 04 PM", "8 41 PM") == -62167144740 func Strtotime(format, strtime string) (int64, error) { t, err := time.Parse(format, strtime) if err != nil { return 0, err } return t.Unix(), nil } // Date date() // Date("02/01/2006 15:04:05 PM", 1524799394) func Date(format string, timestamp int64) string { return time.Unix(timestamp, 0).Format(format) } // Checkdate checkdate() // Validate a Gregorian date func Checkdate(month, day, year int) bool { if month < 1 || month > 12 || day < 1 || day > 31 || year < 1 || year > 32767 { return false } switch month { case 4, 6, 9, 11: if day > 30 { return false } case 2: // leap year if year%4 == 0 && (year%100 != 0 || year%400 == 0) { if day > 29 { return false } } else if day > 28 { return false } } return true } // Sleep sleep() func Sleep(t int64) { time.Sleep(time.Duration(t) * time.Second) } // Usleep usleep() func Usleep(t int64) { time.Sleep(time.Duration(t) * time.Microsecond) } //////////// String Functions //////////// // Strpos strpos() func Strpos(haystack, needle string, offset int) int { length := len(haystack) if length == 0 || offset > length || -offset > length { return -1 } if offset < 0 { offset += length } pos := strings.Index(haystack[offset:], needle) if pos == -1 { return -1 } return pos + offset } // Stripos stripos() func Stripos(haystack, needle string, offset int) int { length := len(haystack) if length == 0 || offset > length || -offset > length { return -1 } haystack = haystack[offset:] if offset < 0 { offset += length } pos := strings.Index(strings.ToLower(haystack), strings.ToLower(needle)) if pos == -1 { return -1 } return pos + offset } // Strrpos strrpos() func Strrpos(haystack, needle string, offset int) int { pos, length := 0, len(haystack) if length == 0 || offset > length || -offset > length { return -1 } if offset < 0 { haystack = haystack[:offset+length+1] } else { haystack = haystack[offset:] } pos = strings.LastIndex(haystack, needle) if offset > 0 && pos != -1 { pos += offset } return pos } // Strripos strripos() func Strripos(haystack, needle string, offset int) int { pos, length := 0, len(haystack) if length == 0 || offset > length || -offset > length { return -1 } if offset < 0 { haystack = haystack[:offset+length+1] } else { haystack = haystack[offset:] } pos = strings.LastIndex(strings.ToLower(haystack), strings.ToLower(needle)) if offset > 0 && pos != -1 { pos += offset } return pos } // StrReplace str_replace() func StrReplace(search, replace, subject string, count int) string { return strings.Replace(subject, search, replace, count) } // Strtoupper strtoupper() func Strtoupper(str string) string { return strings.ToUpper(str) } // Strtolower strtolower() func Strtolower(str string) string { return strings.ToLower(str) } // Ucfirst ucfirst() func Ucfirst(str string) string { for _, v := range str { u := string(unicode.ToUpper(v)) return u + str[len(u):] } return "" } // Lcfirst lcfirst() func Lcfirst(str string) string { for _, v := range str { u := string(unicode.ToLower(v)) return u + str[len(u):] } return "" } // Ucwords ucwords() func Ucwords(str string) string { return strings.Title(str) } // Substr substr() func Substr(str string, start uint, length int) string { if start < 0 || length < -1 { return str } switch { case length == -1: return str[start:] case length == 0: return "" } end := int(start) + length if end > len(str) { end = len(str) } return str[start:end] } // Strrev strrev() func Strrev(str string) string { runes := []rune(str) for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { runes[i], runes[j] = runes[j], runes[i] } return string(runes) } // ParseStr parse_str() // f1=m&f2=n -> map[f1:m f2:n] // f[a]=m&f[b]=n -> map[f:map[a:m b:n]] // f[a][a]=m&f[a][b]=n -> map[f:map[a:map[a:m b:n]]] // f[]=m&f[]=n -> map[f:[m n]] // f[a][]=m&f[a][]=n -> map[f:map[a:[m n]]] // f[][]=m&f[][]=n -> map[f:[map[]]] // Currently does not support nested slice. // f=m&f[a]=n -> error // This is not the same as PHP. // a .[[b=c -> map[a___[b:c] func ParseStr(encodedString string, result map[string]interface{}) error { // build nested map. var build func(map[string]interface{}, []string, interface{}) error build = func(result map[string]interface{}, keys []string, value interface{}) error { length := len(keys) // trim '," key := strings.Trim(keys[0], "'\"") if length == 1 { result[key] = value return nil } // The end is slice. like f[], f[a][] if keys[1] == "" && length == 2 { // todo nested slice if key == "" { return nil } val, ok := result[key] if !ok { result[key] = []interface{}{value} return nil } children, ok := val.([]interface{}) if !ok { return fmt.Errorf("expected type '[]interface{}' for key '%s', but got '%T'", key, val) } result[key] = append(children, value) return nil } // The end is slice + map. like f[][a] if keys[1] == "" && length > 2 && keys[2] != "" { val, ok := result[key] if !ok { result[key] = []interface{}{} val = result[key] } children, ok := val.([]interface{}) if !ok { return fmt.Errorf("expected type '[]interface{}' for key '%s', but got '%T'", key, val) } if l := len(children); l > 0 { if child, ok := children[l-1].(map[string]interface{}); ok { if _, ok := child[keys[2]]; !ok { _ = build(child, keys[2:], value) return nil } } } child := map[string]interface{}{} _ = build(child, keys[2:], value) result[key] = append(children, child) return nil } // map. like f[a], f[a][b] val, ok := result[key] if !ok { result[key] = map[string]interface{}{} val = result[key] } children, ok := val.(map[string]interface{}) if !ok { return fmt.Errorf("expected type 'map[string]interface{}' for key '%s', but got '%T'", key, val) } return build(children, keys[1:], value) } // split encodedString. parts := strings.Split(encodedString, "&") for _, part := range parts { pos := strings.Index(part, "=") if pos <= 0 { continue } key, err := url.QueryUnescape(part[:pos]) if err != nil { return err } for key[0] == ' ' { key = key[1:] } if key == "" || key[0] == '[' { continue } value, err := url.QueryUnescape(part[pos+1:]) if err != nil { return err } // split into multiple keys var keys []string left := 0 for i, k := range key { if k == '[' && left == 0 { left = i } else if k == ']' { if left > 0 { if len(keys) == 0 { keys = append(keys, key[:left]) } keys = append(keys, key[left+1:i]) left = 0 if i+1 < len(key) && key[i+1] != '[' { break } } } } if len(keys) == 0 { keys = append(keys, key) } // first key first := "" for i, chr := range keys[0] { if chr == ' ' || chr == '.' || chr == '[' { first += "_" } else { first += string(chr) } if chr == '[' { first += keys[0][i+1:] break } } keys[0] = first // build nested map if err := build(result, keys, value); err != nil { return err } } return nil } // NumberFormat number_format() // decimals: Sets the number of decimal points. // decPoint: Sets the separator for the decimal point. // thousandsSep: Sets the thousands separator. func NumberFormat(number float64, decimals uint, decPoint, thousandsSep string) string { neg := false if number < 0 { number = -number neg = true } dec := int(decimals) // Will round off str := fmt.Sprintf("%."+strconv.Itoa(dec)+"F", number) prefix, suffix := "", "" if dec > 0 { prefix = str[:len(str)-(dec+1)] suffix = str[len(str)-dec:] } else { prefix = str } sep := []byte(thousandsSep) n, l1, l2 := 0, len(prefix), len(sep) // thousands sep num c := (l1 - 1) / 3 tmp := make([]byte, l2*c+l1) pos := len(tmp) - 1 for i := l1 - 1; i >= 0; i, n, pos = i-1, n+1, pos-1 { if l2 > 0 && n > 0 && n%3 == 0 { for j := range sep { tmp[pos] = sep[l2-j-1] pos-- } } tmp[pos] = prefix[i] } s := string(tmp) if dec > 0 { s += decPoint + suffix } if neg { s = "-" + s } return s } // ChunkSplit chunk_split() func ChunkSplit(body string, chunklen uint, end string) string { if end == "" { end = "\r\n" } runes, erunes := []rune(body), []rune(end) l := uint(len(runes)) if l <= 1 || l < chunklen { return body + end } ns := make([]rune, 0, len(runes)+len(erunes)) var i uint for i = 0; i < l; i += chunklen { if i+chunklen > l { ns = append(ns, runes[i:]...) } else { ns = append(ns, runes[i:i+chunklen]...) } ns = append(ns, erunes...) } return string(ns) } // StrWordCount str_word_count() func StrWordCount(str string) []string { return strings.Fields(str) } // Wordwrap wordwrap() func Wordwrap(str string, width uint, br string, cut bool) string { strlen := len(str) brlen := len(br) linelen := int(width) if strlen == 0 { return "" } if brlen == 0 { panic("break string cannot be empty") } if linelen == 0 && cut { panic("can't force cut when width is zero") } current, laststart, lastspace := 0, 0, 0 var ns []byte for current = 0; current < strlen; current++ { if str[current] == br[0] && current+brlen < strlen && str[current:current+brlen] == br { ns = append(ns, str[laststart:current+brlen]...) current += brlen - 1 lastspace = current + 1 laststart = lastspace } else if str[current] == ' ' { if current-laststart >= linelen { ns = append(ns, str[laststart:current]...) ns = append(ns, br[:]...) laststart = current + 1 } lastspace = current } else if current-laststart >= linelen && cut && laststart >= lastspace { ns = append(ns, str[laststart:current]...) ns = append(ns, br[:]...) laststart = current lastspace = current } else if current-laststart >= linelen && laststart < lastspace { ns = append(ns, str[laststart:lastspace]...) ns = append(ns, br[:]...) lastspace++ laststart = lastspace } } if laststart != current { ns = append(ns, str[laststart:current]...) } return string(ns) } // Strlen strlen() func Strlen(str string) int { return len(str) } // MbStrlen mb_strlen() func MbStrlen(str string) int { return utf8.RuneCountInString(str) } // StrRepeat str_repeat() func StrRepeat(input string, multiplier int) string { return strings.Repeat(input, multiplier) } // Strstr strstr() func Strstr(haystack string, needle string) string { if needle == "" { return "" } idx := strings.Index(haystack, needle) if idx == -1 { return "" } return haystack[idx+len([]byte(needle))-1:] } // Strtr strtr() // // If the parameter length is 1, type is: map[string]string // Strtr("baab", map[string]string{"ab": "01"}) will return "ba01" // If the parameter length is 2, type is: string, string // Strtr("baab", "ab", "01") will return "1001", a => 0; b => 1. func Strtr(haystack string, params ...interface{}) string { ac := len(params) if ac == 1 { pairs := params[0].(map[string]string) length := len(pairs) if length == 0 { return haystack } oldnew := make([]string, length*2) for o, n := range pairs { if o == "" { return haystack } oldnew = append(oldnew, o, n) } return strings.NewReplacer(oldnew...).Replace(haystack) } else if ac == 2 { from := params[0].(string) to := params[1].(string) trlen, lt := len(from), len(to) if trlen > lt { trlen = lt } if trlen == 0 { return haystack } str := make([]uint8, len(haystack)) var xlat [256]uint8 var i int var j uint8 if trlen == 1 { for i = 0; i < len(haystack); i++ { if haystack[i] == from[0] { str[i] = to[0] } else { str[i] = haystack[i] } } return string(str) } // trlen != 1 for { xlat[j] = j if j++; j == 0 { break } } for i = 0; i < trlen; i++ { xlat[from[i]] = to[i] } for i = 0; i < len(haystack); i++ { str[i] = xlat[haystack[i]] } return string(str) } return haystack } // StrShuffle str_shuffle() func StrShuffle(str string) string { runes := []rune(str) r := rand.New(rand.NewSource(time.Now().UnixNano())) s := make([]rune, len(runes)) for i, v := range r.Perm(len(runes)) { s[i] = runes[v] } return string(s) } // Trim trim() func Trim(str string, characterMask ...string) string { if len(characterMask) == 0 { return strings.TrimSpace(str) } return strings.Trim(str, characterMask[0]) } // Ltrim ltrim() func Ltrim(str string, characterMask ...string) string { if len(characterMask) == 0 { return strings.TrimLeftFunc(str, unicode.IsSpace) } return strings.TrimLeft(str, characterMask[0]) } // Rtrim rtrim() func Rtrim(str string, characterMask ...string) string { if len(characterMask) == 0 { return strings.TrimRightFunc(str, unicode.IsSpace) } return strings.TrimRight(str, characterMask[0]) } // Explode explode() func Explode(delimiter, str string) []string { return strings.Split(str, delimiter) } // Chr chr() func Chr(ascii int) string { return string(ascii) } // Ord ord() func Ord(char string) int { r, _ := utf8.DecodeRune([]byte(char)) return int(r) } // Nl2br nl2br() // \n\r, \r\n, \r, \n func Nl2br(str string, isXhtml bool) string { r, n, runes := '\r', '\n', []rune(str) var br []byte if isXhtml { br = []byte("<br />") } else { br = []byte("<br>") } skip := false length := len(runes) var buf bytes.Buffer for i, v := range runes { if skip { skip = false continue } switch v { case n, r: if (i+1 < length) && (v == r && runes[i+1] == n) || (v == n && runes[i+1] == r) { buf.Write(br) skip = true continue } buf.Write(br) default: buf.WriteRune(v) } } return buf.String() } // JSONDecode json_decode() func JSONDecode(data []byte, val interface{}) error { return json.Unmarshal(data, val) } // JSONEncode json_encode() func JSONEncode(val interface{}) ([]byte, error) { return json.Marshal(val) } // Addslashes addslashes() func Addslashes(str string) string { var buf bytes.Buffer for _, char := range str { switch char { case '\'', '"', '\\': buf.WriteRune('\\') } buf.WriteRune(char) } return buf.String() } // Stripslashes stripslashes() func Stripslashes(str string) string { var buf bytes.Buffer l, skip := len(str), false for i, char := range str { if skip { skip = false } else if char == '\\' { if i+1 < l && str[i+1] == '\\' { skip = true } continue } buf.WriteRune(char) } return buf.String() } // Quotemeta quotemeta() func Quotemeta(str string) string { var buf bytes.Buffer for _, char := range str { switch char { case '.', '+', '\\', '(', '$', ')', '[', '^', ']', '*', '?': buf.WriteRune('\\') } buf.WriteRune(char) } return buf.String() } // Htmlentities htmlentities() func Htmlentities(str string) string { return html.EscapeString(str) } // HTMLEntityDecode html_entity_decode() func HTMLEntityDecode(str string) string { return html.UnescapeString(str) } // Md5 md5() func Md5(str string) string { hash := md5.New() hash.Write([]byte(str)) return hex.EncodeToString(hash.Sum(nil)) } // Md5File md5_file() func Md5File(path string) (string, error) { data, err := ioutil.ReadFile(path) if err != nil { return "", err } hash := md5.New() hash.Write([]byte(data)) return hex.EncodeToString(hash.Sum(nil)), nil } // Sha1 sha1() func Sha1(str string) string { hash := sha1.New() hash.Write([]byte(str)) return hex.EncodeToString(hash.Sum(nil)) } // Sha1File sha1_file() func Sha1File(path string) (string, error) { data, err := ioutil.ReadFile(path) if err != nil { return "", err } hash := sha1.New() hash.Write([]byte(data)) return hex.EncodeToString(hash.Sum(nil)), nil } // Crc32 crc32() func Crc32(str string) uint32 { return crc32.ChecksumIEEE([]byte(str)) } // Levenshtein levenshtein() // costIns: Defines the cost of insertion. // costRep: Defines the cost of replacement. // costDel: Defines the cost of deletion. func Levenshtein(str1, str2 string, costIns, costRep, costDel int) int { var maxLen = 255 l1 := len(str1) l2 := len(str2) if l1 == 0 { return l2 * costIns } if l2 == 0 { return l1 * costDel } if l1 > maxLen || l2 > maxLen { return -1 } p1 := make([]int, l2+1) p2 := make([]int, l2+1) var c0, c1, c2 int var i1, i2 int for i2 := 0; i2 <= l2; i2++ { p1[i2] = i2 * costIns } for i1 = 0; i1 < l1; i1++ { p2[0] = p1[0] + costDel for i2 = 0; i2 < l2; i2++ { if str1[i1] == str2[i2] { c0 = p1[i2] } else { c0 = p1[i2] + costRep } c1 = p1[i2+1] + costDel if c1 < c0 { c0 = c1 } c2 = p2[i2] + costIns if c2 < c0 { c0 = c2 } p2[i2+1] = c0 } tmp := p1 p1 = p2 p2 = tmp } c0 = p1[l2] return c0 } // SimilarText similar_text() func SimilarText(first, second string, percent *float64) int { var similarText func(string, string, int, int) int similarText = func(str1, str2 string, len1, len2 int) int { var sum, max int pos1, pos2 := 0, 0 // Find the longest segment of the same section in two strings for i := 0; i < len1; i++ { for j := 0; j < len2; j++ { for l := 0; (i+l < len1) && (j+l < len2) && (str1[i+l] == str2[j+l]); l++ { if l+1 > max { max = l + 1 pos1 = i pos2 = j } } } } if sum = max; sum > 0 { if pos1 > 0 && pos2 > 0 { sum += similarText(str1, str2, pos1, pos2) } if (pos1+max < len1) && (pos2+max < len2) { s1 := []byte(str1) s2 := []byte(str2) sum += similarText(string(s1[pos1+max:]), string(s2[pos2+max:]), len1-pos1-max, len2-pos2-max) } } return sum } l1, l2 := len(first), len(second) if l1+l2 == 0 { return 0 } sim := similarText(first, second, l1, l2) if percent != nil { *percent = float64(sim*200) / float64(l1+l2) } return sim } // Soundex soundex() // Calculate the soundex key of a string. func Soundex(str string) string { if str == "" { panic("str: cannot be an empty string") } table := [26]rune{ // A, B, C, D '0', '1', '2', '3', // E, F, G '0', '1', '2', // H '0', // I, J, K, L, M, N '0', '2', '2', '4', '5', '5', // O, P, Q, R, S, T '0', '1', '2', '6', '2', '3', // U, V '0', '1', // W, X '0', '2', // Y, Z '0', '2', } last, code, small := -1, 0, 0 sd := make([]rune, 4) // build soundex string for i := 0; i < len(str) && small < 4; i++ { // ToUpper char := str[i] if char < '\u007F' && 'a' <= char && char <= 'z' { code = int(char - 'a' + 'A') } else { code = int(char) } if code >= 'A' && code <= 'Z' { if small == 0 { sd[small] = rune(code) small++ last = int(table[code-'A']) } else { code = int(table[code-'A']) if code != last { if code != 0 { sd[small] = rune(code) small++ } last = code } } } } // pad with "0" for ; small < 4; small++ { sd[small] = '0' } return string(sd) } //////////// URL Functions //////////// // ParseURL parse_url() // Parse a URL and return its components // -1: all; 1: scheme; 2: host; 4: port; 8: user; 16: pass; 32: path; 64: query; 128: fragment func ParseURL(str string, component int) (map[string]string, error) { u, err := url.Parse(str) if err != nil { return nil, err } if component == -1 { component = 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 } var components = make(map[string]string) if (component & 1) == 1 { components["scheme"] = u.Scheme } if (component & 2) == 2 { components["host"] = u.Hostname() } if (component & 4) == 4 { components["port"] = u.Port() } if (component & 8) == 8 { components["user"] = u.User.Username() } if (component & 16) == 16 { components["pass"], _ = u.User.Password() } if (component & 32) == 32 { components["path"] = u.Path } if (component & 64) == 64 { components["query"] = u.RawQuery } if (component & 128) == 128 { components["fragment"] = u.Fragment } return components, nil } // URLEncode urlencode() func URLEncode(str string) string { return url.QueryEscape(str) } // URLDecode urldecode() func URLDecode(str string) (string, error) { return url.QueryUnescape(str) } // Rawurlencode rawurlencode() func Rawurlencode(str string) string { return strings.Replace(url.QueryEscape(str), "+", "%20", -1) } // Rawurldecode rawurldecode() func Rawurldecode(str string) (string, error) { return url.QueryUnescape(strings.Replace(str, "%20", "+", -1)) } // HTTPBuildQuery http_build_query() func HTTPBuildQuery(queryData url.Values) string { return queryData.Encode() } // Base64Encode base64_encode() func Base64Encode(str string) string { return base64.StdEncoding.EncodeToString([]byte(str)) } // Base64Decode base64_decode() func Base64Decode(str string) (string, error) { switch len(str) % 4 { case 2: str += "==" case 3: str += "=" } data, err := base64.StdEncoding.DecodeString(str) if err != nil { return "", err } return string(data), nil } //////////// Array(Slice/Map) Functions //////////// // ArrayFill array_fill() func ArrayFill(startIndex int, num uint, value interface{}) map[int]interface{} { m := make(map[int]interface{}) var i uint for i = 0; i < num; i++ { m[startIndex] = value startIndex++ } return m } // ArrayFlip array_flip() func ArrayFlip(m map[interface{}]interface{}) map[interface{}]interface{} { n := make(map[interface{}]interface{}) for i, v := range m { n[v] = i } return n } // ArrayKeys array_keys() func ArrayKeys(elements map[interface{}]interface{}) []interface{} { i, keys := 0, make([]interface{}, len(elements)) for key := range elements { keys[i] = key i++ } return keys } // ArrayValues array_values() func ArrayValues(elements map[interface{}]interface{}) []interface{} { i, vals := 0, make([]interface{}, len(elements)) for _, val := range elements { vals[i] = val i++ } return vals } // ArrayMerge array_merge() func ArrayMerge(ss ...[]interface{}) []interface{} { n := 0 for _, v := range ss { n += len(v) } s := make([]interface{}, 0, n) for _, v := range ss { s = append(s, v...) } return s } // ArrayChunk array_chunk() func ArrayChunk(s []interface{}, size int) [][]interface{} { if size < 1 { panic("size: cannot be less than 1") } length := len(s) chunks := int(math.Ceil(float64(length) / float64(size))) var n [][]interface{} for i, end := 0, 0; chunks > 0; chunks-- { end = (i + 1) * size if end > length { end = length } n = append(n, s[i*size:end]) i++ } return n } // ArrayPad array_pad() func ArrayPad(s []interface{}, size int, val interface{}) []interface{} { if size == 0 || (size > 0 && size < len(s)) || (size < 0 && size > -len(s)) { return s } n := size if size < 0 { n = -size } n -= len(s) tmp := make([]interface{}, n) for i := 0; i < n; i++ { tmp[i] = val } if size > 0 { return append(s, tmp...) } return append(tmp, s...) } // ArraySlice array_slice() func ArraySlice(s []interface{}, offset, length uint) []interface{} { if offset > uint(len(s)) { panic("offset: the offset is less than the length of s") } end := offset + length if end < uint(len(s)) { return s[offset:end] } return s[offset:] } // ArrayRand array_rand() func ArrayRand(elements []interface{}) []interface{} { r := rand.New(rand.NewSource(time.Now().UnixNano())) n := make([]interface{}, len(elements)) for i, v := range r.Perm(len(elements)) { n[i] = elements[v] } return n } // ArrayColumn array_column() func ArrayColumn(input map[string]map[string]interface{}, columnKey string) []interface{} { columns := make([]interface{}, 0, len(input)) for _, val := range input { if v, ok := val[columnKey]; ok { columns = append(columns, v) } } return columns } // ArrayPush array_push() // Push one or more elements onto the end of slice func ArrayPush(s *[]interface{}, elements ...interface{}) int { *s = append(*s, elements...) return len(*s) } // ArrayPop array_pop() // Pop the element off the end of slice func ArrayPop(s *[]interface{}) interface{} { if len(*s) == 0 { return nil } ep := len(*s) - 1 e := (*s)[ep] *s = (*s)[:ep] return e } // ArrayUnshift array_unshift() // Prepend one or more elements to the beginning of a slice func ArrayUnshift(s *[]interface{}, elements ...interface{}) int { *s = append(elements, *s...) return len(*s) } // ArrayShift array_shift() // Shift an element off the beginning of slice func ArrayShift(s *[]interface{}) interface{} { if len(*s) == 0 { return nil } f := (*s)[0] *s = (*s)[1:] return f } // ArrayKeyExists array_key_exists() func ArrayKeyExists(key interface{}, m map[interface{}]interface{}) bool { _, ok := m[key] return ok } // ArrayCombine array_combine() func ArrayCombine(s1, s2 []interface{}) map[interface{}]interface{} { if len(s1) != len(s2) { panic("the number of elements for each slice isn't equal") } m := make(map[interface{}]interface{}, len(s1)) for i, v := range s1 { m[v] = s2[i] } return m } // ArrayReverse array_reverse() func ArrayReverse(s []interface{}) []interface{} { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } return s } // Implode implode() func Implode(glue string, pieces []string) string { var buf bytes.Buffer l := len(pieces) for _, str := range pieces { buf.WriteString(str) if l--; l > 0 { buf.WriteString(glue) } } return buf.String() } // InArray in_array() // haystack supported types: slice, array or map func InArray(needle interface{}, haystack interface{}) bool { val := reflect.ValueOf(haystack) switch val.Kind() { case reflect.Slice, reflect.Array: for i := 0; i < val.Len(); i++ { if reflect.DeepEqual(needle, val.Index(i).Interface()) { return true } } case reflect.Map: for _, k := range val.MapKeys() { if reflect.DeepEqual(needle, val.MapIndex(k).Interface()) { return true } } default: panic("haystack: haystack type muset be slice, array or map") } return false } //////////// Mathematical Functions //////////// // Abs abs() func Abs(number float64) float64 { return math.Abs(number) } // Rand rand() // Range: [0, 2147483647] func Rand(min, max int) int { if min > max { panic("min: min cannot be greater than max") } // PHP: getrandmax() if int31 := 1<<31 - 1; max > int31 { panic("max: max can not be greater than " + strconv.Itoa(int31)) } if min == max { return min } r := rand.New(rand.NewSource(time.Now().UnixNano())) return r.Intn(max+1-min) + min } // Round round() func Round(value float64) float64 { return math.Floor(value + 0.5) } // Floor floor() func Floor(value float64) float64 { return math.Floor(value) } // Ceil ceil() func Ceil(value float64) float64 { return math.Ceil(value) } // Pi pi() func Pi() float64 { return math.Pi } // Max max() func Max(nums ...float64) float64 { if len(nums) < 2 { panic("nums: the nums length is less than 2") } max := nums[0] for i := 1; i < len(nums); i++ { max = math.Max(max, nums[i]) } return max } // Min min() func Min(nums ...float64) float64 { if len(nums) < 2 { panic("nums: the nums length is less than 2") } min := nums[0] for i := 1; i < len(nums); i++ { min = math.Min(min, nums[i]) } return min } // Decbin decbin() func Decbin(number int64) string { return strconv.FormatInt(number, 2) } // Bindec bindec() func Bindec(str string) (string, error) { i, err := strconv.ParseInt(str, 2, 0) if err != nil { return "", err } return strconv.FormatInt(i, 10), nil } // Hex2bin hex2bin() func Hex2bin(data string) (string, error) { i, err := strconv.ParseInt(data, 16, 0) if err != nil { return "", err } return strconv.FormatInt(i, 2), nil } // Bin2hex bin2hex() func Bin2hex(str string) (string, error) { i, err := strconv.ParseInt(str, 2, 0) if err != nil { return "", err } return strconv.FormatInt(i, 16), nil } // Dechex dechex() func Dechex(number int64) string { return strconv.FormatInt(number, 16) } // Hexdec hexdec() func Hexdec(str string) (int64, error) { return strconv.ParseInt(str, 16, 0) } // Decoct decoct() func Decoct(number int64) string { return strconv.FormatInt(number, 8) } // Octdec Octdec() func Octdec(str string) (int64, error) { return strconv.ParseInt(str, 8, 0) } // BaseConvert base_convert() func BaseConvert(number string, frombase, tobase int) (string, error) { i, err := strconv.ParseInt(number, frombase, 0) if err != nil { return "", err } return strconv.FormatInt(i, tobase), nil } // IsNan is_nan() func IsNan(val float64) bool { return math.IsNaN(val) } //////////// Directory/Filesystem Functions //////////// // Stat stat() func Stat(filename string) (os.FileInfo, error) { return os.Stat(filename) } // Pathinfo pathinfo() // -1: all; 1: dirname; 2: basename; 4: extension; 8: filename // Usage: // Pathinfo("/home/go/path/src/php2go/php2go.go", 1|2|4|8) func Pathinfo(path string, options int) map[string]string { if options == -1 { options = 1 | 2 | 4 | 8 } info := make(map[string]string) if (options & 1) == 1 { info["dirname"] = filepath.Dir(path) } if (options & 2) == 2 { info["basename"] = filepath.Base(path) } if ((options & 4) == 4) || ((options & 8) == 8) { basename := "" if (options & 2) == 2 { basename, _ = info["basename"] } else { basename = filepath.Base(path) } p := strings.LastIndex(basename, ".") filename, extension := "", "" if p > 0 { filename, extension = basename[:p], basename[p+1:] } else if p == -1 { filename = basename } else if p == 0 { extension = basename[p+1:] } if (options & 4) == 4 { info["extension"] = extension } if (options & 8) == 8 { info["filename"] = filename } } return info } // FileExists file_exists() func FileExists(filename string) bool { _, err := os.Stat(filename) if err != nil && os.IsNotExist(err) { return false } return true } // IsFile is_file() func IsFile(filename string) bool { _, err := os.Stat(filename) if err != nil && os.IsNotExist(err) { return false } return true } // IsDir is_dir() func IsDir(filename string) (bool, error) { fd, err := os.Stat(filename) if err != nil { return false, err } fm := fd.Mode() return fm.IsDir(), nil } // FileSize filesize() func FileSize(filename string) (int64, error) { info, err := os.Stat(filename) if err != nil && os.IsNotExist(err) { return 0, err } return info.Size(), nil } // FilePutContents file_put_contents() func FilePutContents(filename string, data string, mode os.FileMode) error { return ioutil.WriteFile(filename, []byte(data), mode) } // FileGetContents file_get_contents() func FileGetContents(filename string) (string, error) { data, err := ioutil.ReadFile(filename) return string(data), err } // Unlink unlink() func Unlink(filename string) error { return os.Remove(filename) } // Delete delete() func Delete(filename string) error { return os.Remove(filename) } // Copy copy() func Copy(source, dest string) (bool, error) { fd1, err := os.Open(source) if err != nil { return false, err } defer fd1.Close() fd2, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return false, err } defer fd2.Close() _, e := io.Copy(fd2, fd1) if e != nil { return false, e } return true, nil } // IsReadable is_readable() func IsReadable(filename string) bool { _, err := syscall.Open(filename, syscall.O_RDONLY, 0) if err != nil { return false } return true } // IsWriteable is_writeable() func IsWriteable(filename string) bool { _, err := syscall.Open(filename, syscall.O_WRONLY, 0) if err != nil { return false } return true } // Rename rename() func Rename(oldname, newname string) error { return os.Rename(oldname, newname) } // Touch touch() func Touch(filename string) (bool, error) { fd, err := os.OpenFile(filename, os.O_RDONLY|os.O_CREATE, 0666) if err != nil { return false, err } fd.Close() return true, nil } // Mkdir mkdir() func Mkdir(filename string, mode os.FileMode) error { return os.Mkdir(filename, mode) } // Getcwd getcwd() func Getcwd() (string, error) { dir, err := os.Getwd() return dir, err } // Realpath realpath() func Realpath(path string) (string, error) { return filepath.Abs(path) } // Basename basename() func Basename(path string) string { return filepath.Base(path) } // Chmod chmod() func Chmod(filename string, mode os.FileMode) bool { return os.Chmod(filename, mode) == nil } // Chown chown() func Chown(filename string, uid, gid int) bool { return os.Chown(filename, uid, gid) == nil } // Fclose fclose() func Fclose(handle *os.File) error { return handle.Close() } // Filemtime filemtime() func Filemtime(filename string) (int64, error) { fd, err := os.Open(filename) if err != nil { return 0, err } defer fd.Close() fileinfo, err := fd.Stat() if err != nil { return 0, err } return fileinfo.ModTime().Unix(), nil } // Fgetcsv fgetcsv() func Fgetcsv(handle *os.File, length int, delimiter rune) ([][]string, error) { reader := csv.NewReader(handle) reader.Comma = delimiter // TODO length limit return reader.ReadAll() } // Glob glob() func Glob(pattern string) ([]string, error) { return filepath.Glob(pattern) } //////////// Variable handling Functions //////////// // Empty empty() func Empty(val interface{}) bool { if val == nil { return true } v := reflect.ValueOf(val) switch v.Kind() { case reflect.String, reflect.Array: return v.Len() == 0 case reflect.Map, reflect.Slice: return v.Len() == 0 || v.IsNil() case reflect.Bool: return !v.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return v.Float() == 0 case reflect.Interface, reflect.Ptr: return v.IsNil() } return reflect.DeepEqual(val, reflect.Zero(v.Type()).Interface()) } // IsNumeric is_numeric() // Numeric strings consist of optional sign, any number of digits, optional decimal part and optional exponential part. // Thus +0123.45e6 is a valid numeric value. // In PHP hexadecimal (e.g. 0xf4c3b00c) is not supported, but IsNumeric is supported. func IsNumeric(val interface{}) bool { switch val.(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: return true case float32, float64, complex64, complex128: return true case string: str := val.(string) if str == "" { return false } // Trim any whitespace str = strings.TrimSpace(str) if str[0] == '-' || str[0] == '+' { if len(str) == 1 { return false } str = str[1:] } // hex if len(str) > 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X') { for _, h := range str[2:] { if !((h >= '0' && h <= '9') || (h >= 'a' && h <= 'f') || (h >= 'A' && h <= 'F')) { return false } } return true } // 0-9, Point, Scientific p, s, l := 0, 0, len(str) for i, v := range str { if v == '.' { // Point if p > 0 || s > 0 || i+1 == l { return false } p = i } else if v == 'e' || v == 'E' { // Scientific if i == 0 || s > 0 || i+1 == l { return false } s = i } else if v < '0' || v > '9' { return false } } return true } return false } //////////// Program execution Functions //////////// // Exec exec() // returnVar, 0: succ; 1: fail // Return the last line from the result of the command. // command format eg: // "ls -a" // "/bin/bash -c \"ls -a\"" func Exec(command string, output *[]string, returnVar *int) string { q := rune(0) parts := strings.FieldsFunc(command, func(r rune) bool { switch { case r == q: q = rune(0) return false case q != rune(0): return false case unicode.In(r, unicode.Quotation_Mark): q = r return false default: return unicode.IsSpace(r) } }) // remove the " and ' on both sides for i, v := range parts { f, l := v[0], len(v) if l >= 2 && (f == '"' || f == '\'') { parts[i] = v[1 : l-1] } } cmd := exec.Command(parts[0], parts[1:]...) out, err := cmd.CombinedOutput() if err != nil { *returnVar = 1 return "" } *returnVar = 0 *output = strings.Split(strings.TrimRight(string(out), "\n"), "\n") if l := len(*output); l > 0 { return (*output)[l-1] } return "" } // System system() // returnVar, 0: succ; 1: fail // Returns the last line of the command output on success, and "" on failure. func System(command string, returnVar *int) string { *returnVar = 0 var stdBuf bytes.Buffer var err, err1, err2, err3 error // split command q := rune(0) parts := strings.FieldsFunc(command, func(r rune) bool { switch { case r == q: q = rune(0) return false case q != rune(0): return false case unicode.In(r, unicode.Quotation_Mark): q = r return false default: return unicode.IsSpace(r) } }) // remove the " and ' on both sides for i, v := range parts { f, l := v[0], len(v) if l >= 2 && (f == '"' || f == '\'') { parts[i] = v[1 : l-1] } } cmd := exec.Command(parts[0], parts[1:]...) stdoutIn, _ := cmd.StdoutPipe() stderrIn, _ := cmd.StderrPipe() stdout := io.MultiWriter(os.Stdout, &stdBuf) stderr := io.MultiWriter(os.Stderr, &stdBuf) err = cmd.Start() if err != nil { *returnVar = 1 return "" } go func() { _, err1 = io.Copy(stdout, stdoutIn) }() go func() { _, err2 = io.Copy(stderr, stderrIn) }() err3 = cmd.Wait() if err1 != nil || err2 != nil || err3 != nil { if err1 != nil { fmt.Println(err1) } if err2 != nil { fmt.Println(err2) } if err3 != nil { fmt.Println(err3) } *returnVar = 1 return "" } if output := strings.TrimRight(stdBuf.String(), "\n"); output != "" { pos := strings.LastIndex(output, "\n") if pos == -1 { return output } return output[pos+1:] } return "" } // Passthru passthru() // returnVar, 0: succ; 1: fail func Passthru(command string, returnVar *int) { q := rune(0) parts := strings.FieldsFunc(command, func(r rune) bool { switch { case r == q: q = rune(0) return false case q != rune(0): return false case unicode.In(r, unicode.Quotation_Mark): q = r return false default: return unicode.IsSpace(r) } }) // remove the " and ' on both sides for i, v := range parts { f, l := v[0], len(v) if l >= 2 && (f == '"' || f == '\'') { parts[i] = v[1 : l-1] } } cmd := exec.Command(parts[0], parts[1:]...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err != nil { *returnVar = 1 fmt.Println(err) } else { *returnVar = 0 } } //////////// Network Functions //////////// // Gethostname gethostname() func Gethostname() (string, error) { return os.Hostname() } // Gethostbyname gethostbyname() // Get the IPv4 address corresponding to a given Internet host name func Gethostbyname(hostname string) (string, error) { ips, err := net.LookupIP(hostname) if ips != nil { for _, v := range ips { if v.To4() != nil { return v.String(), nil } } return "", nil } return "", err } // Gethostbynamel gethostbynamel() // Get a list of IPv4 addresses corresponding to a given Internet host name func Gethostbynamel(hostname string) ([]string, error) { ips, err := net.LookupIP(hostname) if ips != nil { var ipstrs []string for _, v := range ips { if v.To4() != nil { ipstrs = append(ipstrs, v.String()) } } return ipstrs, nil } return nil, err } // Gethostbyaddr gethostbyaddr() // Get the Internet host name corresponding to a given IP address func Gethostbyaddr(ipAddress string) (string, error) { names, err := net.LookupAddr(ipAddress) if names != nil { return strings.TrimRight(names[0], "."), nil } return "", err } // IP2long ip2long() // IPv4 func IP2long(ipAddress string) uint32 { ip := net.ParseIP(ipAddress) if ip == nil { return 0 } return binary.BigEndian.Uint32(ip.To4()) } // Long2ip long2ip() // IPv4 func Long2ip(properAddress uint32) string { ipByte := make([]byte, 4) binary.BigEndian.PutUint32(ipByte, properAddress) ip := net.IP(ipByte) return ip.String() } //////////// Misc. Functions //////////// // Echo echo func Echo(args ...interface{}) { fmt.Print(args...) } // Uniqid uniqid() func Uniqid(prefix string) string { now := time.Now() return fmt.Sprintf("%s%08x%05x", prefix, now.Unix(), now.UnixNano()%0x100000) } // Exit exit() func Exit(status int) { os.Exit(status) } // Die die() func Die(status int) { os.Exit(status) } // Getenv getenv() func Getenv(varname string) string { return os.Getenv(varname) } // Putenv putenv() // The setting, like "FOO=BAR" func Putenv(setting string) error { s := strings.Split(setting, "=") if len(s) != 2 { panic("setting: invalid") } return os.Setenv(s[0], s[1]) } // MemoryGetUsage memory_get_usage() // return in bytes func MemoryGetUsage(realUsage bool) uint64 { stat := new(runtime.MemStats) runtime.ReadMemStats(stat) return stat.Alloc } // VersionCompare version_compare() // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively. // special version strings these are handled in the following order, // (any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p // Usage: // VersionCompare("1.2.3-alpha", "1.2.3RC7", '>=') // VersionCompare("1.2.3-beta", "1.2.3pl", 'lt') // VersionCompare("1.1_dev", "1.2any", 'eq') func VersionCompare(version1, version2, operator string) bool { var vcompare func(string, string) int var canonicalize func(string) string var special func(string, string) int // version compare vcompare = func(origV1, origV2 string) int { if origV1 == "" || origV2 == "" { if origV1 == "" && origV2 == "" { return 0 } if origV1 == "" { return -1 } return 1 } ver1, ver2, compare := "", "", 0 if origV1[0] == '#' { ver1 = origV1 } else { ver1 = canonicalize(origV1) } if origV2[0] == '#' { ver2 = origV2 } else { ver2 = canonicalize(origV2) } n1, n2 := 0, 0 for { p1, p2 := "", "" n1 = strings.IndexByte(ver1, '.') if n1 == -1 { p1, ver1 = ver1[:], "" } else { p1, ver1 = ver1[:n1], ver1[n1+1:] } n2 = strings.IndexByte(ver2, '.') if n2 == -1 { p2, ver2 = ver2, "" } else { p2, ver2 = ver2[:n2], ver2[n2+1:] } if (p1[0] >= '0' && p1[0] <= '9') && (p2[0] >= '0' && p2[0] <= '9') { // all is digit l1, _ := strconv.Atoi(p1) l2, _ := strconv.Atoi(p2) if l1 > l2 { compare = 1 } else if l1 == l2 { compare = 0 } else { compare = -1 } } else if !(p1[0] >= '0' && p1[0] <= '9') && !(p2[0] >= '0' && p2[0] <= '9') { // all digit compare = special(p1, p2) } else { // part is digit if p1[0] >= '0' && p1[0] <= '9' { // is digit compare = special("#N#", p2) } else { compare = special(p1, "#N#") } } if compare != 0 || n1 == -1 || n2 == -1 { break } } if compare == 0 { if ver1 != "" { if ver1[0] >= '0' && ver1[0] <= '9' { compare = 1 } else { compare = vcompare(ver1, "#N#") } } else if ver2 != "" { if ver2[0] >= '0' && ver2[0] <= '9' { compare = -1 } else { compare = vcompare("#N#", ver2) } } } return compare } // canonicalize canonicalize = func(version string) string { ver := []byte(version) l := len(ver) if l == 0 { return "" } var buf = make([]byte, l*2) j := 0 for i, v := range ver { next := uint8(0) if i+1 < l { // Have the next one next = ver[i+1] } if v == '-' || v == '_' || v == '+' { // replace '-', '_', '+' to '.' if j > 0 && buf[j-1] != '.' { buf[j] = '.' j++ } } else if (next > 0) && (!(next >= '0' && next <= '9') && (v >= '0' && v <= '9')) || (!(v >= '0' && v <= '9') && (next >= '0' && next <= '9')) { // Insert '.' before and after a non-digit buf[j] = v j++ if v != '.' && next != '.' { buf[j] = '.' j++ } continue } else if !((v >= '0' && v <= '9') || (v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')) { // Non-letters and numbers if j > 0 && buf[j-1] != '.' { buf[j] = '.' j++ } } else { buf[j] = v j++ } } return string(buf[:j]) } // compare special version forms special = func(form1, form2 string) int { found1, found2, len1, len2 := -1, -1, len(form1), len(form2) // (Any string not found) < dev < alpha = a < beta = b < RC = rc < # < pl = p forms := map[string]int{ "dev": 0, "alpha": 1, "a": 1, "beta": 2, "b": 2, "RC": 3, "rc": 3, "#": 4, "pl": 5, "p": 5, } for name, order := range forms { if len1 < len(name) { continue } if strings.Compare(form1[:len(name)], name) == 0 { found1 = order break } } for name, order := range forms { if len2 < len(name) { continue } if strings.Compare(form2[:len(name)], name) == 0 { found2 = order break } } if found1 == found2 { return 0 } else if found1 > found2 { return 1 } else { return -1 } } compare := vcompare(version1, version2) switch operator { case "<", "lt": return compare == -1 case "<=", "le": return compare != 1 case ">", "gt": return compare == 1 case ">=", "ge": return compare != -1 case "==", "=", "eq": return compare == 0 case "!=", "<>", "ne": return compare != 0 default: panic("operator: invalid") } } // ZipOpen zip_open() func ZipOpen(filename string) (*zip.ReadCloser, error) { return zip.OpenReader(filename) } // Pack pack() func Pack(order binary.ByteOrder, data interface{}) (string, error) { buf := new(bytes.Buffer) err := binary.Write(buf, order, data) if err != nil { return "", err } return buf.String(), nil } // Unpack unpack() func Unpack(order binary.ByteOrder, data string) (interface{}, error) { var result []byte r := bytes.NewReader([]byte(data)) err := binary.Read(r, order, &result) if err != nil { return nil, err } return result, nil } // Ternary Ternary expression // max := Ternary(a > b, a, b).(int) func Ternary(condition bool, trueVal, falseVal interface{}) interface{} { if condition { return trueVal } return falseVal }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
2017-04-14 iOS-高性能编程之多线程