21 Star 65 Fork 14

K. / go-agi

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
type_conv.go 17.20 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
package agi
import (
"strconv"
"time"
"math"
"unsafe"
"reflect"
"fmt"
)
// @see http://studygolang.com/articles/2909
func BytesToStrUnsafe(rawBytes []byte) string {
return *(*string)(unsafe.Pointer(&rawBytes))
}
// @see http://shinriyo.hateblo.jp/entry/2015/02/19/Go%E8%A8%80%E8%AA%9E%E3%81%AE%E5%B0%8F%E6%95%B0%E7%82%B9%E3%81%AE%E5%9B%9B%E6%8D%A8%E4%BA%94%E5%85%A5
func Round(f float64, places int) float64 {
shift := math.Pow(10, float64(places))
return math.Floor(f * shift + .5) / shift
}
func StrToFloat(value string) float64 {
float, err := strconv.ParseFloat(value, 64)
if err != nil {
return 0
}
return float
}
// 先尝试转浮点,然后再转整型
func StrToFInt(value string) int {
float := StrToFloat(value)
return int(float)
}
func StrToFInt64(value string) int64 {
float := StrToFloat(value)
return int64(float)
}
func StrToInt(value string) int {
number, err := strconv.Atoi(value)
if err == nil {
return number
}
return 0
}
// 取得整型值所表达的布尔类型
// 不同于golang提供的ParseBool
func StrToIntBool(value string) bool {
// "" => false
if len(value) <= 0 {
return false
}
i := StrToFInt(value) // 先尝试尽量取得这个字符串表示的整型值
if i <= 0 {
return false
}
return true
}
// 将字符串的时间表示,转为时间,注意是类似2014-12-31,不是整型值
// 如果要指定时区解析,直接调用time.ParseInLocation吧
func StrToTime(value string, layout string) time.Time {
// Mon Jan 2 15:04:05 -0700 MST 2006
t, err := time.ParseInLocation(layout, value, AppTimeLoc())
if err != nil {
return time.Time{}
}
return t
// fmt.Println(t.Unix(), err)
// fmt.Println(time.Unix(t.Unix(), 0).Format("2006-01-02 15:04:05"))
}
func IntToTime(value int64) time.Time {
if value <= 0 {
return time.Time{}
}
return time.Unix(value, 0)
}
// go的时间
// var t = time.Time {} => t.IsZero() => true
// var t = time.Unix(0, 0) => t.IsZero() => false
func IsValidTime(t time.Time) bool {
if t.IsZero() {
return false
}
if t.Unix() <= 0 {
return false
}
return true
}
func CallAnyMethod(v interface{}, method string) interface{} {
ref := reflect.ValueOf(v)
refKind := ref.Kind()
if refKind == reflect.Ptr {
refKind = ref.Elem().Kind()
}
// 如果是结构的话,尝试检索一下他是否有Int、ToInt的函数
// 不再限制为Struct
// if refKind == reflect.Struct {
fn := ref.MethodByName(method)
if fn.IsValid() {
rs := fn.Call(nil)
if len(rs) > 0 {
return rs[0].Interface()
}
}
// }
return nil
}
// Kind在reflect已经有比较明确的枚举,能比较方便的去进行比较
func KindOf(v interface {}) reflect.Kind {
ref := reflect.ValueOf(v)
refKind := ref.Kind()
if refKind == reflect.Ptr {
return ref.Elem().Kind()
}
return refKind
}
func ValueOf(v interface {}) reflect.Value {
ref := reflect.ValueOf(v)
refKind := ref.Kind()
if refKind == reflect.Ptr {
return ref.Elem()
}
return ref
}
// 转型最好优先转型到最大的值,然后再往底缩进
// 更精确的做法,应该是根据位长,来做出适当的判断但过度优化,又不如直接用go提供一些方法
// 所以这个方法只是确保值的有效性转换,性能在能考虑的条件下,才考虑
func AnyToInt64(v interface{}) int64 {
switch v.(type) {
// #1
// 这个nil必须保持,不然在检索结构的方法时,有可能会陷入死循环
case nil : return 0
// #2
case bool : if v == true { return 1 }
// #3
// 这玩意可真算不上优雅啊,go怎么就没有泛型呢?
case int : if conv, ok := v.(int); ok { return int64(conv) }
case int8 : if conv, ok := v.(int8); ok { return int64(conv) }
case int16 : if conv, ok := v.(int16); ok { return int64(conv) }
case int32 : if conv, ok := v.(int32); ok { return int64(conv) }
case int64 : if conv, ok := v.(int64); ok { return int64(conv) }
case uint : if conv, ok := v.(uint); ok { return int64(conv) }
case uint8 : if conv, ok := v.(uint8); ok { return int64(conv) }
case uint16 : if conv, ok := v.(uint16); ok { return int64(conv) }
case uint32 : if conv, ok := v.(uint32); ok { return int64(conv) }
case uint64 : if conv, ok := v.(uint64); ok { return int64(conv) } // 这里仍然是有问题
// #4
case float32 : if conv, ok := v.(float32); ok { return int64(conv) }
case float64 : if conv, ok := v.(float64); ok { return int64(conv) }
// #5
case string : if conv, ok := v.(string); ok { return StrToFInt64(conv) }
// #6
case time.Time : if conv, ok := v.(time.Time); ok { return conv.Unix() }
// #999
default :
rs := CallAnyMethod(v, "Int")
if rs != nil {
return AnyToInt64(rs)
} else {
return KindToInt64(v)
}
}
return 0
}
func AnyToInt(v interface{}) int {
return int(AnyToInt64(v))
}
// 小位数的整型,还是经常会用到的
// 溢出值,以溢出的最大值处理,而不要作为负数处理
// 256 / 2
func AnyToInt8(v interface{}) int8 {
iv := AnyToInt64(v)
if iv > 127 { // 0 - 127
return int8(127)
} else if iv < -128 { // -128 - -1
return int8(-128)
}
return int8(iv)
}
// 小位数的整型,还是经常会用到的
// 溢出值,以溢出的最大值处理,而不要作为负数处理
// 65536 / 2
func AnyToInt16(v interface{}) int16 {
iv := AnyToInt64(v)
if iv > 32767 { // 0 - 127
return int16(32767)
} else if iv < -32768 { // -128 - -1
return int16(-32768)
}
return int16(iv)
}
func AnyToUInt64(v interface{}) uint64 {
return uint64(AnyToInt64(v))
}
// 无负数的小位数整型,其实也是很常用到的
func AnyToUInt8(v interface{}) uint8 {
iv := AnyToInt64(v)
if iv > 255 { // 0 - 127
return uint8(255)
} else if iv < 0 { // -128 - -1
return uint8(0)
}
return uint8(iv)
}
// 无负数的小位数整型,其实也是很常用到的,32的就自己手动转吧,uint32能表达的值意境非常大了
func AnyToUInt16(v interface{}) uint16 {
iv := AnyToInt64(v)
if iv > 65535 { // 0 - 127
return uint16(65535)
} else if iv < 0 { // -128 - -1
return uint16(0)
}
return uint16(iv)
}
func AnyToBool(v interface{}) bool {
switch v.(type) {
// #1
// 这个nil必须保持,不然在检索结构的方法时,有可能会陷入死循环
case nil : return false
// #2
case bool : if v == true { return true }
// #3
// 这玩意可真算不上优雅啊,go怎么就没有泛型呢?
case int : if conv, ok := v.(int); ok { return conv > 0 }
case int8 : if conv, ok := v.(int8); ok { return conv > 0 }
case int16 : if conv, ok := v.(int16); ok { return conv > 0 }
case int32 : if conv, ok := v.(int32); ok { return conv > 0 }
case int64 : if conv, ok := v.(int64); ok { return conv > 0 }
case uint : if conv, ok := v.(uint); ok { return conv > 0 }
case uint8 : if conv, ok := v.(uint8); ok { return conv > 0 }
case uint16 : if conv, ok := v.(uint16); ok { return conv > 0 }
case uint32 : if conv, ok := v.(uint32); ok { return conv > 0 }
case uint64 : if conv, ok := v.(uint64); ok { return conv > 0 }
// #4
case float32 : if conv, ok := v.(float32); ok { return conv > 0 }
case float64 : if conv, ok := v.(float64); ok { return conv > 0 }
// #5
case string : if conv, ok := v.(string); ok { return len(conv) > 0 }
// #6
case time.Time : if conv, ok := v.(time.Time); ok { return IsValidTime(conv) }
// #999
default :
kind := KindOf(v)
val := ValueOf(v)
if kind == reflect.Slice || kind == reflect.Array || kind == reflect.Map {
return val.Len() > 0
} else if kind == reflect.Struct {
// 结构真的没什么好判断的,只要不是无效的结构,就只好返回true了
if val.IsValid() {
return true
}
}
}
return false
}
// 注意,所有其他的AnyTo转换,都不处理[]byte,因为实际上[]byte的情况会比较复杂,他可能包含了encode/gob的编码格式,也可能是json格式
// 也可能用户自己打包的,所以我们不做任何处理
// 但AnyToStr的话还是要处理,尝试最简单的转换
func AnyToStr(v interface{}) string {
switch v.(type) {
// #1
// 这个nil必须保持,不然在检索结构的方法时,有可能会陷入死循环
case nil : return ""
// #2
// 布尔类型,应该返回个啥呢?真头疼,暂时先返回一个1吧,总比返回了true好
case bool : if v == true { return "1" }
// #3
// 这玩意可真算不上优雅啊,go怎么就没有泛型呢?
case int : if conv, ok := v.(int); ok { return strconv.Itoa(conv) }
case int8 : if conv, ok := v.(int8); ok { return strconv.Itoa(int(conv)) }
case int16 : if conv, ok := v.(int16); ok { return strconv.Itoa(int(conv)) }
case int32 : if conv, ok := v.(int32); ok { return strconv.Itoa(int(conv)) } // 32bit 64bit系统都能涵盖了这个值
case int64 : if conv, ok := v.(int64); ok { return fmt.Sprint(conv) }
case uint : if conv, ok := v.(uint); ok { return fmt.Sprint(conv) }
case uint8 : if conv, ok := v.(uint8); ok { return strconv.Itoa(int(conv)) }
case uint16 : if conv, ok := v.(uint16); ok { return strconv.Itoa(int(conv)) }
case uint32 : if conv, ok := v.(uint32); ok { return fmt.Sprint(conv) } // 32无负数整型,转int就少了一截了
case uint64 : if conv, ok := v.(uint64); ok { return fmt.Sprint(conv) } // 64位无负数整型,就更加是少了一截了。
// #4
case float32 : if conv, ok := v.(float32); ok { return strconv.FormatFloat(float64(conv), 'f', -1, 64) }
case float64 : if conv, ok := v.(float64); ok { return strconv.FormatFloat(conv, 'f', -1, 64) }
// #5
case []byte : if conv, ok := v.([]byte); ok { return string(conv) }
case string : if conv, ok := v.(string); ok { return conv }
// #6
case time.Time : if conv, ok := v.(time.Time); ok { return conv.String() }
// #999
default :
// 数组、切片、Map转类型是什么类型呢?
return AnyToStr(CallAnyMethod(v, "String"))
}
return ""
}
func AnyToFloat(v interface{}) float64 {
switch v.(type) {
// #1
// 这个nil必须保持,不然在检索结构的方法时,有可能会陷入死循环
case nil : return 0
// #2
case bool : if v == true { return 1 }
// #3
// 这玩意可真算不上优雅啊,go怎么就没有泛型呢?
case int : if conv, ok := v.(int); ok { return float64(conv) }
case int8 : if conv, ok := v.(int8); ok { return float64(conv) }
case int16 : if conv, ok := v.(int16); ok { return float64(conv) }
case int32 : if conv, ok := v.(int32); ok { return float64(conv) }
case int64 : if conv, ok := v.(int64); ok { return float64(conv) }
case uint : if conv, ok := v.(uint); ok { return float64(conv) }
case uint8 : if conv, ok := v.(uint8); ok { return float64(conv) }
case uint16 : if conv, ok := v.(uint16); ok { return float64(conv) }
case uint32 : if conv, ok := v.(uint32); ok { return float64(conv) }
case uint64 : if conv, ok := v.(uint64); ok { return float64(conv) } // 这里仍然是有问题
// #4
case float32 : if conv, ok := v.(float32); ok { return float64(conv) }
case float64 : if conv, ok := v.(float64); ok { return float64(conv) }
// #5
case string : if conv, ok := v.(string); ok { return StrToFloat(conv) }
// #6
case time.Time : if conv, ok := v.(time.Time); ok { return float64(conv.Unix()) }
// #999
default :
// 数组、切片、Map转类型是什么类型呢?
return AnyToFloat(CallAnyMethod(v, "Float"))
}
return 0
}
func AnyToRound(v interface{}, places int) float64 {
return Round(AnyToFloat(v), places)
}
func AnyToTime(v interface{}) time.Time {
switch v.(type) {
// #1
// 这个nil必须保持,不然在检索结构的方法时,有可能会陷入死循环
case nil :
return time.Time{}
// #2
// 布尔类型,应该返回个啥呢?真头疼,暂时先返回一个1吧,总比返回了true好
case bool :
if v == true {
return time.Now()
}
// #3
case int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64:
return time.Unix(AnyToInt64(v), 0)
// #4
case float32, float64 :
return time.Unix(AnyToInt64(v), 0)
// #5
case string :
if conv, ok := v.(string); ok {
return StrToTime(conv, "Y-m-d H:i:s")
}
// #6
case time.Time :
// 时间格式,该转成什么字符串呢?
if conv, ok := v.(time.Time); ok {
return conv // 先返回默认的字符表达值吧
}
// #999
default :
// 数组、切片、Map转类型是什么类型呢?
return AnyToTime(CallAnyMethod(v, "Time"))
}
return time.Time{}
}
func KindToInt64(v interface{}) int64 {
kind := KindOf(v)
value := ValueOf(v)
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64 :
return value.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64 :
return AnyToInt64(value.Uint())
case reflect.Float32, reflect.Float64 :
return AnyToInt64(value.Float())
case reflect.String :
return AnyToInt64(value.String())
case reflect.Bool :
return AnyToInt64(value.Bool())
case reflect.Struct :
if value.Type().String() == "time.Time" {
if conv, ok := v.(time.Time); ok { return conv.Unix() }
}
}
return 0
}
// 这是网上找到的一种做法,但是还没测试过
//func GetBytes(v interface{}) ([]byte, error) {
// var buf bytes.Buffer
// enc := gob.NewEncoder(&buf)
// err := enc.Encode(v)
// if err != nil {
// return nil, err
// }
// return buf.Bytes(), nil
//}
//
//func BytesDecode(raw []byte, v interface{}) (interface{}, error) {
// buf := bytes.NewBuffer(raw)
// dec := gob.NewDecoder(buf)
// err := dec.Decode(&v)
// if err != nil {
// return nil, err
// }
// return v, err
//}
//
//// 这里实现的比较丑陋一点……
//func AnyToBytes(v interface{}) []byte {
// switch v.(type) {
// // #1
// // 这个nil必须保持,不然在检索结构的方法时,有可能会陷入死循环
// case nil :
// return nil
// // #2
// // 布尔类型,应该返回个啥呢?真头疼,暂时先返回一个1吧,总比返回了true好
// case bool :
// if v == true {
// return []byte {1}
// } else {
// return []byte {0}
// }
// return nil
// // #3
// case int, int32, int64 :
// if conv, ok := v.(int); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, int64(conv))
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// case int8 :
// if conv, ok := v.(int8); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv)
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// case int16 :
// if conv, ok := v.(int16); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv)
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// case uint8 :
// if conv, ok := v.(uint8); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv)
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// case uint16 :
// if conv, ok := v.(uint16); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv)
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// case uint32 :
// if conv, ok := v.(uint32); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv)
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// case uint64 :
// if conv, ok := v.(uint32); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv)
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// // #4
// case float32, float64 :
// if conv, ok := v.(float64); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv)
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// // #5
// case string :
// if conv, ok := v.(string); ok {
// return []byte(conv)
// }
// // #6
// case time.Time :
// if conv, ok := v.(time.Time); ok {
// buf := new(bytes.Buffer)
// err := binary.Write(buf, osEndian, conv.Unix())
// if err == nil {
// return buf.Bytes()
// }
// return nil
// }
// // #7
// case []byte :
// if conv, ok := v.([]byte); ok {
// return conv
// }
// // #999
// default :
// // 数组、切片、Map怎么转bytes呢? json encode?
// return AnyToBytes(CallAnyStructMethod(v, "Bytes"))
// }
// return nil
//}
Go
1
https://gitee.com/janpoem/go-agi.git
git@gitee.com:janpoem/go-agi.git
janpoem
go-agi
go-agi
master

搜索帮助