Golang 更新函数内部的结构字段作为接口传递

问题描述 投票:0回答:2

我是新来的(golang)。这就是为什么我的问题可能无关紧要(或无法回答)的原因。

我创建了两个结构。这两个都嵌入了另一个结构。现在我想更新函数内嵌入结构的字段。

package main

import (
    "fmt"
    "reflect"
    "time"
)

type Model struct {
    UpdatedAt time.Time
}

type Fruit struct {
    Model
    label string
}

type Animal struct {
    Model
    label string
}

func update(v interface{}) {
    reflectType := reflect.TypeOf(v)
    reflectKind := reflectType.Kind()
    if reflectKind == reflect.Ptr {
        reflectType = reflectType.Elem()
    }
    m := reflect.Zero(reflectType)
    fmt.Println(m)
}

func main() {
    apple := &Fruit{
        label: "Apple",
    }
    tiger := &Animal{
        label: "Tiger",
    }
    update(apple)
    update(tiger)
    fmt.Println(apple)
    fmt.Println(tiger)
}

我希望实现

update
函数,以便它将当前时间放入传递的结构的
UpdatedAt
中。但我做不到。

在这种情况下,

Fruit
Animal
的领域是相同的:
label
。但它不会永远如此。请在提供建议时记住这一点。

任何指导将不胜感激。

go struct reflection interface embedding
2个回答
6
投票

如果您开始学习围棋,我会避免使用

reflect
interface{}
。初学者通常会像
void *
拐杖一样依靠它们。尝试使用具体类型或定义明确的接口。

这应该让你去:

type Timestamper interface {
    Update()
    UpdatedTime() time.Time
}

type Model struct {
    updated time.Time
}

func (m *Model) Update()                { m.updated = time.Now() }
func (m *Model) UpdatedTime() time.Time { return m.updated }

type Fruit struct {
    Model
    label string
}

type Animal struct {
    Model
    label string
}

// update will work with a `Model` `Animal` or `Fruit`
// as they all implement the `Timestamper` interface`
func update(v Timestamper) {
    v.Update()
}

游乐场:https://play.golang.org/p/27yDVLr-zqd


3
投票

假设你想通过反射来实现:首先,你必须传递一个指向结构的指针。您现在正在传递结构的副本,因此在

update
中所做的任何修改都将在副本上完成,而不是在您传入的实例上完成。然后,您可以在传入的接口中查找字段
UpdatedAt
,并设置它。

也就是说,这可能不是最好的方法。另一种无需反思的方法是:

func update(in *Model) {
   in.UpdatedAt = time.Now()
}

func main() {
   apple := &Fruit{}
   update(&apple.Model)
}

或:

func (in *Model) update() {
   in.UpdatedAt = time.Now()
}

func main() {
   apple := &Fruit{}
   apple.update()
}
© www.soinside.com 2019 - 2024. All rights reserved.