我正在使用gorm,它允许许多数据类型,例如
然后我在模板中有一个这样的插件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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类型并将其强制转换为
我已经搜索了许多天,以解决方案将
- 你应该做什么?你想达到什么目的?
-
@Flimzy我不想列出所有整数类型,并且只用一行就可以了。如
return time.Unix(int64(t.(trueType)), 0).Format(f) 。您没有在这里看到麻烦吗?使用单个功能,我至少要切换/切换8次才能完成一个简单的任务 -
@Flimzy
I have searched many days for solution convert interface{} to its true type without using type assertion but didnt work. 没读过这一行吗? - 我看不到麻烦,因为我看不到你想完成什么。您只关注特定的解决方案,但尚未解释问题。您需要该switch语句的原因是什么?您要达到的目标是什么?
- 多年来,我一直使用Go来通过gorm和类似的库进行数据库访问,但从未感到像问题中那样需要大型switch语句。几乎可以肯定有一种解决问题的不同方法,但是在不知道目标的情况下很难说。换句话说,这看起来像XY问题。
- @Flimzy我只是想避免在不使用switch / case的情况下将所有整数类型转换为字符串时出错。如果您可以提供其他方法,请执行此操作。我从其他语言切换到了Go,缺少通用名称会给我带来很多麻烦。这就是例子。
-
在我看来,他可能正在将行结果写入映射,而不是直接写入结构,然后稍后自己进行转换。我之前做过此事,并开始获取
[]uint8 之类的类型,而不是我期望的类型 - 您的目标是提供一种将Unix时间戳转换为格式化日期字符串的格式化功能。那是对的吗?
根据您的评论,听起来您正在考虑将任何数字类型转换为字符串。这可以通过
1 | stringValue := fmt.Sprint(i) // i is any type |
但这与GORM无关。
另一方面,如果您的问题是GORM返回的是不可预测的类型,则只需将select语句更改为始终返回字符串即可。例如,对于MySQL,类似:
1 | SELECT CAST(someNumberColumn AS VARCHAR) AS stringColumn |
要么
1 | SELECT CAST(someNumberColumn AS INT) AS intColumn |
-
Gorm支持指针类型和普通类型,日期时间字段可以是
int 或*int ,因此这意味着如果字段类型是指针,则模板函数无法将其转换为字符串 - 我不知道您在谈论什么模板功能,但是由于此问题与模板无关,因此可能需要解决一个单独的问题。
-
这是问题的一部分。您看到我在问题
*int 中提到了指针类型,而Sprint(*i) 不适用于指针类型
我没有使用过gorm,但是我认为这样可以解决您的问题:
1 2 3 4 5 6 7 8 | 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 } |
它没有列出所有可能的类型,而是仅使用
我认为这不是go或gorm的问题。我为将unix时间戳保存为许多不同格式而感到困惑。顺便说一句,unix时间戳是32位,因此转换(并保存在首位)任何8位int没有意义。
一种解决方案是对结构中的所有时间戳使用统一的数据类型(int64)。之后,格式化功能可以接受
-
我没有说这是gorm的问题。它的golang问题,它不支持泛型。这就是为什么我们必须使用switch / case来声明所有类型的原因。使用
int64 会导致内存。为什么我必须使用int64 与字段只有0,1,2数字。这是设计模式,我们不能强迫其他开发人员在日期时间字段中仅使用int64 ,而gorm 支持每种整数类型,这意味着任何人都可以在所需的任何字段中使用任何类型,因此逻辑代码必须处理所有它的。 -
我不建议对所有数字字段使用int64。只需将其用于时间戳即可。如果您担心内存,可以使用int32,但是对于unix时间戳,它应该至少为32位。打印出任何其他数字作为格式化的日期字符串实际上没有任何意义,还是我遗漏了一些东西?因为有可能,并不意味着您应该使用它。为什么要对相同类型的数据使用任意数量的数据类型?指定所有时间戳以32位保存是明智的惯例。然后,您的函数可以接受
int32 而不是interface{} 。 -
有数百万的代码逻辑。类似于上面的示例:将unixtimestamp(整数数据字段)转换为格式化的字符串。从那时起,gorm支持所有类型的整数。您将如何解决此问题?就像我说的那样,明智的约定或常识是基于每个开发人员的观点,并非每个人都具有相同的编码风格,为了行善,我们必须将所有情况都包含在代码逻辑中。使用
Sprint 实际上是一个不错的技巧,但不是解决拥有泛型之类问题的正确方法 - 抱歉,我只是想提供帮助。我试图以我的知识和理解来回答您的问题。