如何限制 interface{} 为特定类型

huangapple go评论82阅读模式
英文:

How to limit interface{} for specific types

问题

我正在使用Go语言,我有一个工厂函数,根据请求的标识符返回不同类型的对象:

func NewObject(id string) interface{} {
    switch id {
    case "truck":
        return Truck{}
    case "car":
        return Car{}
    ....
    }
}

这里是相应的结构体类型:

type Truck struct {
    Foo string
}

type Car struct {
    Bar string
}

正如你所看到的,Truck和Car没有任何共同之处。问题在于,当调用NewObject(..)时,我现在必须处理过于宽泛的类型interface{}。我知道有泛型,但这将要求在类型约束中保留所有支持的类型的列表,这会使我的代码变得复杂。

基本上,我正在寻找一种在这里使用继承的方法,而Go当然不支持继承。有什么替代方案吗?

英文:

I am using Go and I have a factory function that returns different types of objects, depending on a requested identifier:

func NewObject(id string) interface{} {
    switch id {
    case "truck":
        return Truck{}
    case "car":
        return Car{}
    ....
    }
}

Here are the respective struct types:

type Truck struct {
    Foo string
}

type Car struct {
    Bar string
}

As you can see, Truck and Car don't have anything in common. The problem arises from the fact that I now have to deal with the too broad type interface{} when calling NewObject(..). I know there are generics, but this would require to keep a list of all supported types in the type constraints that would complicate things in my code base.

Basically I am looking for a way on how to use inheritance here which Go of course doesn't support. What would be the alternative?

答案1

得分: 1

NewObject(..)函数可以通过__泛型__的支持来实现。您不需要在类型约束中保留所有支持的类型的列表。


func NewObject[T any](id string) T {
 var vehicle any

 switch id {

 case "truck":
  vehicle = Truck{
   Foo: "foo",
  }
 case "car":
  vehicle = Car{
   Bar: "bar",
  }
 }

 if val, ok := vehicle.(T); ok {
  return val
 }

 var otherVehicle T
 fmt.Printf("未实现。返回\"%v\"的默认值\n", id)
 return otherVehicle
}

您可以在这里查看完整的示例。

英文:

NewObject(..) function can be implemented with the support of generics. You don't need to keep a list of all supported types in the type constraints.


func NewObject[T any](id string) T {
 var vehicle any

 switch id {

 case "truck":
  vehicle = Truck{
   Foo: "foo",
  }
 case "car":
  vehicle = Car{
   Bar: "bar",
  }
 }

 if val, ok := vehicle.(T); ok {
  return val
 }

 var otherVehicle T
 fmt.Printf("Not implemented. Returning with default values for \"%v\"\n", id)
 return otherVehicle
}

You can see complete example here.

答案2

得分: 1

我有一个奇怪的例子

这个例子将返回struct的构造

希望这能给你一些启发

package main

import (
	"fmt"
)

type testA struct {
	a uint
}
type testB struct {
	b string
}

var mp map[string]func(...interface{}) interface{} = map[string]func(...interface{}) interface{}{
	"struct1": func(para ...interface{}) interface{} {
		return &testA{
			a: para[0].(uint),
		}
	},
	"struct2": func(para ...interface{}) interface{} {
		return &testB{
			b: para[0].(string),
		}
	},
}

func NewSpecial(type_check_str string) func(...interface{}) interface{} {
	if val, ok := mp[type_check_str]; ok {
		return val
	}
	return nil
}

func main() {

	test1 := NewSpecial("struct1")(uint(5))
	test2 := NewSpecial("struct2")("It's Ok?")
	fmt.Println(test1)
	fmt.Println(test2)
}
英文:

I have an odd example

This example will return construct of struct

Hope this inspire you

package main

import (
	"fmt"
)

type testA struct {
	a uint
}
type testB struct {
	b string
}

var mp map[string]func(...interface{}) interface{} = map[string]func(...interface{}) interface{}{
	"struct1": func(para ...interface{}) interface{} {
		return &testA{
			a: para[0].(uint),
		}
	},
	"struct2": func(para ...interface{}) interface{} {
		return &testB{
			b: para[0].(string),
		}
	},
}

func NewSpecial(type_check_str string) func(...interface{}) interface{} {
	if val, ok := mp[type_check_str]; ok {
		return val
	}
	return nil
}

func main() {

	test1 := NewSpecial("struct1")(uint(5))
	test2 := NewSpecial("struct2")("It's Ok?")
	fmt.Println(test1)
	fmt.Println(test2)
}

huangapple
  • 本文由 发表于 2023年4月13日 04:48:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75999703.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定