英文:
Passing time.Time as parameter to generic function
问题
尝试在time.Time
中使用泛型。
总体目标是接受time.Time
或毫秒作为int64
。
这段代码返回错误:
> 无法将't'(类型T)用作time.Time类型
type SomeTime struct {
At time.Time
}
func PointFactory[T time.Time](at T) *SomeTime {
return &SomeTime{
At: at,
}
}
是否可以将time.Time
作为参数传递给泛型函数?
谢谢。
英文:
Trying to use generics with time.Time
.
The general goal was to accept time.Time
or milliseconds as int64
This code return the error:
> Cannot use 'at' (type T) as the type time.Time
type SomeTime struct {
At time.Time
}
func PointFactory[T time.Time](at T) *SomeTime {
return &SomeTime{
At: at,
}
}
Is it possible to pass time.Time
as parameter to generic function?
Thanks
答案1
得分: 3
你可以将T参数转换为任意类型,然后使用类型切换来创建所需的结构体:
package main
import (
"fmt"
"time"
)
type SomeTime struct {
At time.Time
}
func PointFactory[T interface{}](at T) *SomeTime {
switch v := at.(type) {
case time.Time:
fmt.Println("time")
return &SomeTime{
At: v,
}
case int64:
fmt.Println("int")
return &SomeTime{
At: time.Unix(v, 0),
}
}
return nil
}
func main() {
fmt.Println(PointFactory(int64(6)))
fmt.Println(PointFactory(time.Now()))
}
输出结果:
int
&{1970-01-01 00:00:06 +0000 UTC}
time
&{2009-11-10 23:00:00 +0000 UTC m=+0.000000001}
这是因为Go团队的决定:
在此设计的早期版本中,我们允许在类型参数的类型或基于类型参数的类型上使用类型断言和类型切换。我们删除了这个功能,因为始终可以将任何类型的值转换为空接口类型,然后在其上使用类型断言或类型切换。此外,在使用近似元素的类型集的约束中,有时会令人困惑的是,类型断言或类型切换将使用实际的类型参数,而不是类型参数的基础类型(该差异在匹配的预声明类型的标识部分中有解释)。
英文:
The closest you can get is to cast your T param to any then use a type switch to make the desired structs:
package main
import (
"fmt"
"time"
)
type SomeTime struct {
At time.Time
}
func PointFactory[T time.Time | int64](at T) *SomeTime {
switch any(at).(type) {
case time.Time:
fmt.Println("time")
return &SomeTime{
At: v,
}
case int64:
fmt.Println("int")
return &SomeTime{
At: time.Unix(v, 0),
}
}
return nil
}
func main() {
fmt.Println(PointFactory(int64(6)))
fmt.Println(PointFactory(time.Now()))
}
Output:
int
&{1970-01-01 00:00:06 +0000 UTC}
time
&{2009-11-10 23:00:00 +0000 UTC m=+0.000000001}
This is because the decision of the Go team:
> In an earlier version of this design, we permitted using type assertions and type switches on variables whose type was a type parameter, or whose type was based on a type parameter. We removed this facility because it is always possible to convert a value of any type to the empty interface type, and then use a type assertion or type switch on that. Also, it was sometimes confusing that in a constraint with a type set that uses approximation elements, a type assertion or type switch would use the actual type argument, not the underlying type of the type argument (the difference is explained in the section on identifying the matched predeclared type)
答案2
得分: 1
你可以这样声明多个类型:
func say[T string | int](msg T) {
fmt.Println(msg)
}
func main() {
say(1)
say("hello")
}
参见 playground
根据你的问题,你可以重新定义你的函数。你可以使用:
PointFromInt(n int) *SomeTime {...}
PointFromTime(t time.Time) *SomeTime {...}
你的用例可能不适合使用泛型。或者常规的类型化函数可能更适合。
英文:
You may declare multiple type as such:
func say[T string | int](msg T) {
fmt.Println(msg)
}
func main() {
say(1)
say("hello")
}
See playground
Now as per your question, may you redefine your functions ? You may use:
PointFromInt(n int) *SomeTime {...}
PointFromTime(t time.Time) *SomeTime {...}
Your usecase may not be a good candidate for generics. Or regular typed function may do a better job.
答案3
得分: 0
package main
import (
"fmt"
"time"
)
func main() {
fmt.Printf("%v\n", PointFactory(time.Now()).At)
fmt.Printf("%v\n", PointFactory(time.Now().Unix()).At)
}
type SomeTime[T time.Time | int64] struct {
At T
}
func PointFactory[T time.Time | int64](at T) *SomeTime[T] {
return &SomeTime[T]{
At: at,
}
}
package main
import (
"fmt"
"time"
)
func main() {
fmt.Printf("%v\n", PointFactory(time.Now()).At)
fmt.Printf("%v\n", PointFactory(time.Now().Unix()).At)
}
type SomeTime[T time.Time | int64] struct {
At T
}
func PointFactory[T time.Time | int64](at T) *SomeTime[T] {
return &SomeTime[T]{
At: at,
}
}
英文:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Printf("%v\n", PointFactory(time.Now()).At)
fmt.Printf("%v\n", PointFactory(time.Now().Unix()).At)
}
type SomeTime[T time.Time | int64] struct {
At T
}
func PointFactory[T time.Time | int64](at T) *SomeTime[T] {
return &SomeTime[T]{
At: at,
}
}
答案4
得分: 0
如果Sometime
结构体预期接受time.Time
或int64
类型的值,那么它需要声明这个类型,并且方法将值设置为At
,具体是哪种类型取决于可用的类型。
type SomeTime[T time.Time | int64] struct {
At T
}
func PointFactoryTime(at time.Time) *SomeTime[time.Time] {
return &SomeTime[time.Time]{
At: at,
}
}
func PointFactoryInt64(at int64) *SomeTime[int64] {
return &SomeTime[int64]{
At: at,
}
}
英文:
If the Sometime
struct is expected to accept time.Time
or int64
then it needs to declare it, the methods set the value to At
what type is available
type SomeTime[T time.Time | int64] struct {
At T
}
func PointFactoryTime(at time.Time) *SomeTime[time.Time] {
return &SomeTime[time.Time]{
At: at,
}
}
func PointFactoryInt64(at int64) *SomeTime[int64] {
return &SomeTime[int64]{
At: at,
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论