jjzjj

json - 我该怎么做呢?将结构作为接口(interface)发送到函数并将其作为结构取回?

coder 2024-07-10 原文

我是 golang 开发的新手,对与 this question 相关的事情有一些疑问.

作为学习练习,我正在尝试创建一个简单的库来处理基于 json 的配置文件。作为用于多个应用程序的配置文件,它应该能够处理不同的参数。然后我创建了一个具有文件名和数据接口(interface)的类型结构配置。每个应用程序都会根据其配置需求有一个结构。

在下面的代码中,我将所有内容(lib 和“主要代码”)放在一起,“TestData 结构”是“应用程序参数”。 如果它不存在,它将设置默认值并创建文件,并且它正在工作。但是当我尝试读取文件时。我尝试解码 json 并将其放回数据接口(interface)。但它给了我一个错误,我不知道如何解决这个问题。有人可以帮忙吗?

[更新] 我之前没有放置目标代码,因为我认为将所有代码作为一个程序读起来会更容易。贝娄是“目标代码”,可以更好地了解问题。 由于我将无法在库中使用 TestData 结构,因为它会因程序而异,处理此问题的唯一方法是使用接口(interface)。有没有更好的办法?

库配置

package config

import (
    "encoding/json"
    "fmt"
    "os"
)

// Base configuration struct
type Configuration struct {
    Filename string
    Data     interface{}
}

func (c *Configuration) Create(cData *Configuration) bool {
    cFile, err := os.Open(cData.Filename)
    defer cFile.Close()
    if err == nil {
        fmt.Println("Error(1) trying to create a configuration file. File '", cData.Filename, "' may already exist...")
        return false
    }
    cFile, err = os.Create(cData.Filename)
    if err != nil {
        fmt.Println("Error(2) trying to create a configuration file. File '", cData.Filename, "' may already exist...")
        return false
    }
    buffer, _ := json.MarshalIndent(cData.Data, "", "")
    cFile.Write(buffer)
    return true
}

func (c *Configuration) Read(cData *Configuration) bool {
    cFile, err := os.Open(cData.Filename)
    defer cFile.Close()
    if err != nil {
        fmt.Println("Error(1) trying to read a configuration file. File '", cData.Filename, "' may not already exist...")
        return false
    }
    jConfig := json.NewDecoder(cFile)
    jerr := jConfig.Decode(&cData.Data)
    if jerr != nil {
        panic(jerr)
    }
    return true
}

使用库配置的程序

package main

import (
    "fmt"

    "./config"
)

// struct basic para configuração
type TestData struct {
    URL  string
    Port string
}

func main() {
    var Config config.Configuration
    Config.Filename = "config.json"

    if !Config.Read(&Config) {
        Config.Data = TestData{"http", "8080"}
        Config.Create(&Config)
    }
    fmt.Println(Config.Data)
    TestData1 := &TestData{}
    TestData1 = Config.Data.(*TestData) // error, why?
    fmt.Println(TestData1.URL)
}

新更新: 在 JimB 评论说我不清楚某些概念并尝试复习后,我做了一些更改。不幸的是,当然很多事情对我来说还不清楚。我相信我得到了“大”的理解,但让我心烦意乱的是值、格式和指针的“输入”和“输出”,主要是当它转到其他库时。我还不能遵循它的“完整路径”。

然而,我相信我有一些进步on my code .

我认为我已经纠正了一些点,但还有一些大问题:

  1. 我停止发送“配置”作为参数,因为所有“数据”都已经存在,因为它们在实例中是“thenselfs”。对吧?
  2. 为什么我在第 58 行 (Config.Data = &TestData{}) 中有 use 引用
  3. 为什么我必须在第 64 行中使用指针 (tmp := Config.Data.(*TestData)
  4. 为什么我不能在第 69 行使用引用 (Config.Data = tmp)

谢谢

最佳答案

您遇到错误的原因是因为您正在尝试解码为 interface{} 类型。在处理 JSON 对象时,它们默认被 encoding/json 包解码为 map[string]interface{} 类型。这导致类型断言失败,因为 map[string]interface{} 的内存结构与结构的内存结构有很大不同。

更好的方法是让您的 TestData 结构符合您的配置结构的预期数据格式:

// Base configuration struct
type Configuration struct {
    Filename string
    Data     *TestData
}

然后在解码文件数据时,包会将数据解码到与它找到的数据最匹配的字段中。

如果您需要对数据解码过程进行更多控制,您可以使用结构标记指定将哪些 JSON 字段解码为哪些结构成员。您可以在此处阅读有关可用的 json 结构标签的更多信息:https://golang.org/pkg/encoding/json/#Marshal

关于json - 我该怎么做呢?将结构作为接口(interface)发送到函数并将其作为结构取回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35327063/

有关json - 我该怎么做呢?将结构作为接口(interface)发送到函数并将其作为结构取回?的更多相关文章

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

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

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  4. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  5. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

  6. ruby - 怎么来的(a_method || :other) returns :other only when assigning to a var called a_method? - 2

    给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R

  7. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  8. ruby-on-rails - 我该怎么办 :remote location validation with CarrierWave? - 2

    我在我的Rails3示例应用程序上使用CarrierWave。我想验证远程位置上传,因此当用户提交无效URL(空白或非图像)时,我不会收到标准错误异常:CarrierWave::DownloadErrorinImageController#createtryingtodownloadafilewhichisnotservedoverHTTP这是我的模型:classPaintingtrue,:length=>{:minimum=>5,:maximum=>100}validates:image,:presence=>trueend这是我的Controller:classPaintingsC

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

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

  10. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

随机推荐