上下文为 Go 语言库编写 URL 查询参数解析器问题只有结构在Go中具有我所知道的继承形式。可以使用反射包来辨别实体的类型,即它是类型系统中的基本存储类,并且可以探测所述元素的类型。因此,我可以辨别出该实体是 Kind 字符串,并且类型 Title 作为任意示例,假设存在类似这样的东西:type Title string更好的是,对于结构,我可以使用匿名成员来获得有限类型的继承:type Foo struct { name string }func (f Foo) Hello() string { return f.name; }type Bar struct { Foo }func main() { b := Bar{ Foo{"Simon"} } fmt.Println(b.Hello())}实际示例关键是,Go允许我将Foo扩展为Bar,但至少对于Foo的部分继承/重用Foo函数。但是,对于非结构类型 - 我不知道如何为类似于json或xml的编码/解码库解决这个问题 - 我希望能够将查询参数解码为结构的成员,并且至关重要的是,能够支持用户定义的类型,而不需要它们中的每一个都为我的目的定义一个专门的解码器或编码器, 只要它们是支持我可以利用的接口的类型的衍生品。具体来说,我想支持存储为Google uuid的用户定义类型。UUID,或一个时间。时间(或时间。持续时间也将是有用的)。下面是一个简单的示例:type TransactionID uuid.UUID如前所述,这将继承 uuid 的零行为。UUID,我不确定是否或如何使用反射来故意在我的编码器/解码器库中发生这种情况?Go本身不会在它们之间提供任何形式的继承或关系。我的事务 ID 不是 uuid。UUID,但它们共享相同的种类 - 一个[16]字节数组,据我目前所知,这就是它们共享的全部内容。这是我的难题如何允许我希望支持的用户定义类型,而无需我的用户现在为其类型定义我已经为“基本”类型定义的相同编码器或解码器函数?更多背景信息我的解码器库提供此接口:// Parser is an interface for types that RequestParser can parse from a URL parametertype Parser interface { ParseParameter(value string) error}我为uuid定义了一个专门的扩展。UUID 和时间。Time 和其他一些有用的非结构类型,用于从查询参数字符串中解码它们。如果我正在解码的实体类型实际上是一个uuid。UUID 或一个时间。时间而不是基于这些的用户定义类型,然后事情就会正常工作。同样,用户别名之所以有效,是因为它们不是真正的新类型。别名对于我的目的来说太有限了 - 它们没有提供与别名类型的任何有意义的区别,这严重限制了它们的实际效用。我不会回应需要使用它们的建议。谢谢。更新理想情况下,用户应该能够为他们的目的定义TransalID,我想知道它是一种“一种”UUID,因此 - 默认情况下 - 使用UUID解析器。用户定义:func (id *TransactionID) ParseParameter(value string) (err error) { id_, err := uuid.Parse(value) if err != nil { return } *id = TransactionID(id_) return}这将迫使我的解码器选择他们明确定义的接口 - 并完全按照他们希望的类型解码输入。我希望 - 是有一种方法可以知道他们的类型是____的衍生类型是什么?,如果我有一个____的解析器是什么 - 那么 - 在没有用户定义的ParseParameter的情况下 - 使用我默认提供的智能(知道[16]字节与UUID不是一回事, 并了解更复杂的解码UUID的方法)。补遗我将扩展这个问题,并在我得到深思熟虑和有用的答复时提供更多细节。我不确定在这一点上我还能提供什么?感谢您花时间深思熟虑地回复,如果您选择这样做。
1 回答
慕容708150
TA贡献1831条经验 获得超4个赞
无法使用反射 API 来辨别一个类型是从另一个类型创建的。
规范说:
类型定义创建一个新的、不同的类型,其基础类型和操作与给定类型相同,并将标识符绑定到该类型。
和
新类型称为已定义类型。它不同于任何其他类型,包括创建它的类型。
该规范未定义已定义类型与创建该类型时所基于的类型之间的任何其他关系。没有“创建自”关系供反射 API 公开。
在示例中
type A B
反射 API 无法告诉您类型 A 是从类型 B 创建的,因为除了共享的基础类型之外,类型 A 和类型 B 之间没有关系。
允许从 A 到 B 和 B 到 A 的类型转换,因为 A 和 B 具有相同的基础类型。
您可以使用反射 API 来确定两个类型是否具有相同的基础类型,但这对解决问题没有帮助。可能是A是从B创建的,B是从A创建的,或者两者都不是从另一个创建的。在此示例中,类型 A 和 B 具有相同的基础类型:
type A int type B int
问题指出,解析器具有 的内置解码器。目标是将该解析器用于 。以下是解决此问题的一些方法:uuid.UID
type TransactionID uuid.UUID
嵌入将类型声明为 。检查具有单个已知嵌入字段的结构并相应地进行处理。type TransactionID struct { uuid.UID }
注册表添加函数函数以注册可转换类型之间的映射。
var decodeAs = map[reflect.Type]reflect.Type{} func RegisterDecodeAs(target, decode reflect.Type) { if !decode.ConvertibleTo(target) { panic("type must be convertible") } decodeAs[target] = decode }
解码时,请检查 中的解码类型。如果存在,则解码为解码类型,转换为目标类型并分配。decodeAs
在程序启动时调用注册函数:
func init() { RegisterDecodeAs(reflect.TypeOf(TransactionID(nil)), reflect.TypeOf(uuid.UUID(nil)) }
- 1 回答
- 0 关注
- 70 浏览
添加回答
举报
0/150
提交
取消