使用 Golang 解决没有泛型的类型断言?
Solution for type assertion without generics with Golang?
我正在使用 gorm,它允许许多数据类型,例如 int, uint, int8, uint8 ....
然后我在模板中有一个这样的插件:
f["UNIX2STR"] = func(t interface{}, f string) string {
switch t.(type) {
case int:
return time.Unix(int64(t.(int)), 0).Format(f)
case uint:
return time.Unix(int64(t.(uint)), 0).Format(f)
case uint8:
return time.Unix(int64(t.(uint8)), 0).Format(f)
case *int:
return time.Unix(int64(*t.(*int)), 0).Format(f)
case *uint:
return time.Unix(int64(*t.(*uint)), 0).Format(f)
case *uint8:
return time.Unix(int64(*t.(*uint8)), 0).Format(f)
.....
default:
return ""
}
// return time.Unix(int64(t), 0).Format(f)
}
它将所有整数类型转换为格式化字符串。
那我该怎么办?列出所有 gorm 支持的 int 类型并将其转换为 int64
?
我已经搜索了很多天的解决方案,在不使用类型断言的情况下将 interface{}
转换为它的真实类型,但没有成功。
我没用过 gorm,但我认为这样的东西可以解决你的问题:
func formatUnix(t interface{}, f string) (string, error) {
timestampStr := fmt.Sprint(t)
timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
if err != nil {
return "", err
}
return time.Unix(timestamp, 0).Format(f), nil
}
它没有列出所有可能的类型,它只是使用 fmt.Sprint()
将 interface{}
转换为 string
,然后使用 string
转换为 int64
strconv.ParseInt()
.
根据您的评论,您似乎关心将任何数字类型转换为字符串。使用 fmt.Sprint
:
很容易做到这一点
stringValue := fmt.Sprint(i) // i is any type
但这与GORM无关。
另一方面,如果您的问题是 GORM 是 return 不可预测的类型,只需将您的 select 语句更改为始终 return 字符串。例如,对于 MySQL,类似于:
SELECT CAST(someNumberColumn AS VARCHAR) AS stringColumn
或
SELECT CAST(someNumberColumn AS INT) AS intColumn
我认为这不是 go 或 gorm 的问题。我有点困惑你以多种不同的格式保存你的 unix 时间戳。顺便说一句,unix 时间戳是 32 位的,所以转换(并首先保存)任何 8 位整数是没有意义的。
一种解决方案是对结构中的所有时间戳使用统一数据类型 (int64)。之后,您的格式化函数可以接受 int64
而不是 interface{}
,而无需任何类型断言。
我正在使用 gorm,它允许许多数据类型,例如 int, uint, int8, uint8 ....
然后我在模板中有一个这样的插件:
f["UNIX2STR"] = func(t interface{}, f string) string {
switch t.(type) {
case int:
return time.Unix(int64(t.(int)), 0).Format(f)
case uint:
return time.Unix(int64(t.(uint)), 0).Format(f)
case uint8:
return time.Unix(int64(t.(uint8)), 0).Format(f)
case *int:
return time.Unix(int64(*t.(*int)), 0).Format(f)
case *uint:
return time.Unix(int64(*t.(*uint)), 0).Format(f)
case *uint8:
return time.Unix(int64(*t.(*uint8)), 0).Format(f)
.....
default:
return ""
}
// return time.Unix(int64(t), 0).Format(f)
}
它将所有整数类型转换为格式化字符串。
那我该怎么办?列出所有 gorm 支持的 int 类型并将其转换为 int64
?
我已经搜索了很多天的解决方案,在不使用类型断言的情况下将 interface{}
转换为它的真实类型,但没有成功。
我没用过 gorm,但我认为这样的东西可以解决你的问题:
func formatUnix(t interface{}, f string) (string, error) {
timestampStr := fmt.Sprint(t)
timestamp, err := strconv.ParseInt(timestampStr, 10, 64)
if err != nil {
return "", err
}
return time.Unix(timestamp, 0).Format(f), nil
}
它没有列出所有可能的类型,它只是使用 fmt.Sprint()
将 interface{}
转换为 string
,然后使用 string
转换为 int64
strconv.ParseInt()
.
根据您的评论,您似乎关心将任何数字类型转换为字符串。使用 fmt.Sprint
:
stringValue := fmt.Sprint(i) // i is any type
但这与GORM无关。
另一方面,如果您的问题是 GORM 是 return 不可预测的类型,只需将您的 select 语句更改为始终 return 字符串。例如,对于 MySQL,类似于:
SELECT CAST(someNumberColumn AS VARCHAR) AS stringColumn
或
SELECT CAST(someNumberColumn AS INT) AS intColumn
我认为这不是 go 或 gorm 的问题。我有点困惑你以多种不同的格式保存你的 unix 时间戳。顺便说一句,unix 时间戳是 32 位的,所以转换(并首先保存)任何 8 位整数是没有意义的。
一种解决方案是对结构中的所有时间戳使用统一数据类型 (int64)。之后,您的格式化函数可以接受 int64
而不是 interface{}
,而无需任何类型断言。