草庐IT

arrays - Golang,将嵌入式结构转换为数组

coder 2023-06-29 原文

有没有办法在 Golang 中将结构转换为值数组?

例如,如果我有这种结构(不只是这个):

type Model struct {
    Id        bson.ObjectId   `bson:"_id,omitempty"`
    CreatedAt time.Time       `bson:",omitempty"`
    UpdatedAt time.Time       `bson:",omitempty"`
    DeletedAt time.Time       `bson:",omitempty"`
    CreatedBy bson.ObjectId   `bson:",omitempty"`
    UpdatedBy bson.ObjectId   `bson:",omitempty"`
    DeletedBy bson.ObjectId   `bson:",omitempty"`
    Logs      []bson.ObjectId `bson:",omitempty"`
}

type User struct {
    Name  string `bson:"name"`
    Model `bson:",inline"`
}

情况是,我通常以这种格式将 JSON 发送到浏览器:

var iota = -1
var data = {
  NAME: ++iota, ID: ++iota, CREATED_AT: ++iota, UPDATED_AT: ++iota, DELETED_AT: ++iota, // and so on
  rows: [['kiz',1,'2014-01-01','2014-01-01','2014-01-01'],
         ['yui',2,'2014-01-01','2014-01-01','2014-01-01'],
         ['ham',3,'2014-01-01','2014-01-01','2014-01-01'] // and so on
        ]
};

代替:

var data = {
  rows: [{NAME:'kiz',ID:1,CreatedAt:'2014-01-01',UpdatedAt:'2014-01-01',DeletedAt:'2014-01-01'},
         {NAME:'yui',ID:2,CreatedAt:'2014-01-01',UpdatedAt:'2014-01-01',DeletedAt:'2014-01-01'},
         {NAME:'ham',ID:3,CreatedAt:'2014-01-01',UpdatedAt:'2014-01-01',DeletedAt:'2014-01-01'} // and so on
        ]
}

这是我尝试过的:

import (
    "github.com/kr/pretty"
    //"gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "reflect"
    "runtime"
    "strings"
    "time"
)

// copy the model from above

func Explain(variable interface{}) {
    _, file, line, _ := runtime.Caller(1)
    //res, _ := json.MarshalIndent(variable, "   ", "  ")
    res := pretty.Formatter(variable)
    fmt.Printf("%s:%d: %# v\n", file[len(FILE_PATH):], line, res)
    //spew.Dump(variable)
}

func s2a(i interface{}) []interface{} { // taken from https://gist.github.com/tonyhb/5819315
    iVal := reflect.ValueOf(i).Elem()
    //typ := iVal.Type()
    values := make([]interface{}, 0, iVal.NumField())
    for i := 0; i < iVal.NumField(); i++ {
        f := iVal.Field(i)
        //tag := typ.Field(i).Tag.Get("tagname")
        //fmt.Println(tag)
        // name := typ.Field(i).Name
        v := f.Interface()
        switch v.(type) {
        case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, string, []byte, time.Time:
            // do nothing
        // case struct{}: // how to catch any embeeded struct?
        case Model: // Model (or any embedded/nameless struct) should also converted to array
            //arr := s2a() // invalid type assertion: f.(Model) (non-interface type reflect.Value on left)
            //arr := s2a(f.Addr().(&Model)) // invalid type assertion: f.Addr().(&Model) (non-interface type reflect.Value on left)
            // umm.. how to convert f back to Model?
            //for _, e := range arr {
                values = append(values, e)
            //}
        default: // struct? but also interface and map T_T
            //v = s2a(&v)
        }
        values = append(values, v)
    }
    return values
}

func main() {
    //sess, err := mgo.Dial("127.0.0.1")
    //Check(err, "unable to connect")
    //db := sess.DB("test")
    //coll := db.C("coll1")
    user := User{}
    user.Id = bson.NewObjectId()
    user.Name = "kis"
    //changeInfo, err := coll.UpsertId(user.Id, user)
    //Check(err, "failed to insert")
    //Explain(changeInfo)
    //Explain(s2a(changeInfo))
    user.Name = "test"
    Explain(user)
    Explain(s2a(&user))
    //err = coll.FindId(user.Id).One(&user)
    //Check(err, "failed to fetch")
    //Explain(user)
    //Explain(s2a(&user))
    user.CreatedAt = time.Now()
    //err = coll.UpdateId(user.Id, user)
    //Check(err, "failed to update")
    Explain(changeInfo)
    Explain(s2a(&user))
    user.CreatedAt = user.DeletedAt
    //err = coll.FindId(user.Id).One(&user)
    //Check(err, "failed to fetch")
    Explain(user)
    Explain(s2a(&user))
}

是否有简单/快速的方法将结构转换为数组(如果结构嵌入/内部,也转换为数组)?

最佳答案

如果您愿意为数组表示中的字段指定固定顺序,您可以通过实现 json.Marshaler interface 来实现自定义其表示。例如:

func (u User) MarshalJSON() ([]byte, error) {
    a := []interface{}{
        u.Name,
        u.Id,
        ...,
    }
    return json.Marshal(a)
}

现在,当您编码这种类型的变量时,它们将被表示为一个数组。如果你还想做相反的事情(将数组解码到这个结构中),你还需要实现 json.Unmarshaler interface .这可以以类似的方式完成,使用 json.Unmarshal 解码为 []interface{} slice ,然后提取值。确保 UnmarshalJSON 被声明为采用指针接收器,否则您的代码将无法工作(您最终将更新结构的副本而不是结构本身)。

关于arrays - Golang,将嵌入式结构转换为数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27141037/

有关arrays - Golang,将嵌入式结构转换为数组的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

    我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

  3. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  4. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  5. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  6. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  7. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  8. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  9. arrays - 这是 Ruby 中 Array.fill 方法的错误吗? - 2

    这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]

  10. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

随机推荐