如何阅读结构体字段的装饰器?

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

How to read struct field ` ` decorators?

问题

我的包需要让用户能够显式地定义后端数据库列名,如果他们想要的话。

默认情况下,我将使用字段名作为列名,但有时他们需要手动指定列名,就像JSON包中的unmarshal函数一样,如果需要的话会使用显式名称。

我该如何在我的代码中使用这个显式值?我甚至不知道它叫什么,所以谷歌现在真的让我失望。

以下是JSON的unmarshal函数的示例:

type User struct {
    Name string
    LastName    string  `json:"last_name"`
    CategoryId  int     `json:"category_id"`
}

我需要使用类似这样的东西吗?

// Paprika是我的包名。
type User struct {
    Name string
    LastName    string   `paprika:"last_name"`
    CategoryId  int      `paprika:"category_id"`
}

我的包将构建SQL查询,我不能仅仅依赖字段名,我需要让他们能够手动设置列名。所以目前只能使用已定义的列。

// 使用反射提取资源信息并保存字段名和类型。
func loadTypeToSchema(resource interface{}) {
    resourceType := reflect.TypeOf(resource)

    // 获取资源结构体名称。
    fullName := resourceType.String()
    name := fullName[strings.Index(fullName, ".")+1:]

    // 获取资源结构体的字段和类型。
    fieldCount := resourceType.NumField()
    fields := make(map[string]string)
    for i := 0; i <= fieldCount-1; i++ {
        field := resourceType.Field(i)
        fields[field.Name] = field.Type.Name()
    }

    // 将资源信息添加到模式映射中。
    schema[name] = fields
}
英文:

My package needs to be able to let my users define the fields backend database column name explicitly, if they want to.

By default I will use the fields name - but sometimes they will need to manually specify the column name, just like the JSON package - unmarshal uses the explicit name if required.

How can I consume this explicit value in my code? I don't even know what it's called so Google is really failing me at the moment.

Here's what JSON's unmarshal function needs for example:

type User struct {
    Name string
    LastName    string  `json:&quot;last_name&quot;`
    CategoryId  int     `json:&quot;category_id&quot;`
}

What would I need to use something like this?

// Paprika is my package name.
type User struct {
    Name string
    LastName    string   `paprika:&quot;last_name&quot;`
    CategoryId  int      `paprika:&quot;category_id&quot;`
}

My package will be constructing SQL queries and I can't just rely on the field's name - I need to be able to let them manually set the column name. So this is working with only the defined columns at the moment.

// Extracts resource information using reflection and
// saves field names and types.
func loadTypeToSchema(resource interface{}) {
	resourceType := reflect.TypeOf(resource)

	// Grab the resource struct Name.
	fullName := resourceType.String()
	name := fullName[strings.Index(fullName, &quot;.&quot;)+1:]

	// Grabs the resource struct fields and types.
	fieldCount := resourceType.NumField()
	fields := make(map[string]string)
	for i := 0; i &lt;= fieldCount-1; i++ {
		field := resourceType.Field(i)
		fields[field.Name] = field.Type.Name()
	}

	// Add resource information to schema map.
	schema[name] = fields
}

答案1

得分: 9

首先,你所称之为装饰器实际上被称为标签。你可以使用反射来读取这些标签。reflect包甚至有自己的示例

不过,这里有另一个示例,它打印出结构体成员的所有标签(点击播放):

type Foo struct {
    A int `tag for A`
    B int `tag for B`
    C int
}

func main() {
    f := Foo{}
    t := reflect.TypeOf(f)
    
    for i := 0; i < t.NumField(); i++ {
        fmt.Println(t.Field(i).Tag)
    }
}

请注意,如果f是一个指针,例如*Foo,你需要先对该值进行间接引用(解引用),否则TypeOf返回的类型不是结构体,而是指针,NumFieldField()也无法工作。

英文:

First of all, what you call decorators are actually called tags. You can read these tags using reflection. The reflect package even has its own example for that.

Nevertheless, here's another example that prints all tags of the members of a struct (Click to play):

type Foo struct {
	A int `tag for A`
	B int `tag for B`
	C int
}

func main() {
	f := Foo{}
	t := reflect.TypeOf(f)
	
	for i := 0; i &lt; t.NumField(); i++ {
		fmt.Println(t.Field(i).Tag)
	}
}

Note that in case f is a pointer, e.g. a *Foo, you'd have to indirect (dereference) that value first or else the type returned by TypeOf is not a struct but a pointer and NumField as well as Field() would not work.

huangapple
  • 本文由 发表于 2014年5月24日 09:17:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/23840362.html
匿名

发表评论

匿名网友

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

确定