天道酬勤,学无止境

一种处理嵌入一个公共结构的所有结构类型的方法(json 编组)(One method to handle all the struct types that embed one common struct (json marshalling))

问题

我有一个带有 MVC 架构的 gin-gonic Web 应用程序。 我创建了几个模型,它们都嵌入了一个通用结构:

type User struct {
   ID int
   Name string
}

type Admin struct {
   User
   Level int
}

... {
   User
}

现在我想将它们以 json 格式存储在数据库中。 我想要完成的目标是只编写一个函数/方法来编组任何模型并将其保存到数据库中。 此方法必须编组当前模型的所有字段,而不仅仅是来自 User 结构,例如 User 必须编组到{id: 1, name: "zhora"} ,而 Admin 将进入{id: 1, name: "gena", level: 2}

像这个:

func (i *User) Save() {
  data, err := json.Marshal(i)
  check(err)
  if i.ID == 0 {
    _, err = app.DB.Exec(`INSERT INTO users(data) VALUES ($1) `, string(data))
  } else {
    _, err = app.DB.Exec(`UPDATE users SET data = $1 WHERE id=$2`, string(data), i.ID)
  }
  check(err)
}

现在我必须将此func复制/粘贴到每个模型文件中,只更改方法接收器。 这可以避免吗?

回答1

你可以像这样使用一个func Save(d interface{})

package main

import (
    "encoding/json"
    "fmt"
)

type User struct {
    ID   int
    Name string
}

type Admin struct {
    User
    Level int
}

func main() {
    Save(User{})
    Save(Admin{})
}

func Save(d interface{}) {
    body, err := json.Marshal(d)
    if err != nil {
        panic(err)
    }
    st := string(body)
    fmt.Println(st)
}

输出:

{"ID":0,"Name":""}
{"ID":0,"Name":"","Level":0}

对于您的情况,请对所有类型使用此功能:

func Save(i interface{}, id int) {
    data, err := json.Marshal(i)
    check(err)
    if id == 0 {
        _, err = app.DB.Exec(`INSERT INTO users(data) VALUES ($1) `, string(data))
    } else {
        _, err = app.DB.Exec(`UPDATE users SET data = $1 WHERE id=$2`, string(data), id)
    }
    check(err)
}

并这样称呼它:

u := User{}
a := Admin{}

Save(u, u.ID)
Save(a, a.ID)

是的,这甚至简化了对Save到一个参数的调用:

package main

import (
    "encoding/json"
    "fmt"
)

type Model interface {
    ID() int
    setID(int)
}

type User struct {
    Id   int
    Name string
}

func (t User) ID() int      { return t.Id }
func (t User) setID(id int) { t.Id = id }

type Admin struct {
    User
    Level int
}

func main() {
    Save(User{})
    Save(Admin{})
}

func Save(d Model) {
    body, err := json.Marshal(d)
    if err != nil {
        panic(err)
    }
    st := string(body)
    fmt.Println(st)

    fmt.Println("ID is ", d.ID())
}

输出:

{"Id":0,"Name":""}
ID is  0
{"Id":0,"Name":"","Level":0}
ID is  0

现在您可以对所有类型使用这个函数:

func Save(i Model) {
    data, err := json.Marshal(i)
    check(err)
    id := i.ID()
    if id == 0 {
        _, err = app.DB.Exec(`INSERT INTO users(data) VALUES ($1) `, string(data))
    } else {
        _, err = app.DB.Exec(`UPDATE users SET data = $1 WHERE id=$2`, string(data), id)
    }
    check(err)
}

并这样称呼它:

u := User{}
a := Admin{}

Save(u)
Save(a)

有效去:

吸气剂

Go 不提供对 getter 和 setter 的自动支持。 自己提供 getter 和 setter 并没有错,而且这样做通常是合适的,但是将 Get 放在 getter 的名称中既不惯用,也没有必要。 如果您有一个名为 owner(小写,未导出)的字段,则 getter 方法应称为 Owner(大写,已导出),而不是 GetOwner。 使用大写名称导出提供了区分字段和方法的钩子。 如果需要,setter 函数可能会被称为 SetOwner。 这两个名字在实践中都很好读:

 owner := obj.Owner() if owner != user { obj.SetOwner(user) }

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 将任意字段添加到未知结构的 json 输出(Adding Arbitrary fields to json output of an unknown struct)
    问题 在这个 stackoverflow 帖子中,解释了如何通过将其用作匿名来将任意字段添加到 golang 结构中。 如果您正在使用已知的结构类型,这很好用,但我想知道在处理未知的结构或接口时如何做同样的事情。 我写了下面的例子来演示: package main import ( "os" "encoding/json" "fmt" ) type example interface{} type Data struct { Name string } func printInterface(val interface{}) { example1 := struct { example Extra string }{ example: val, Extra: "text", } json.NewEncoder(os.Stdout).Encode(example1) } func printStructPointer(val *Data) { example2 := struct { *Data Extra string }{ Data: val, Extra: "text", } json.NewEncoder(os.Stdout).Encode(example2) } func main() { d := Data{Name:"name"} fmt.Println(
  • 如何不在Go中将空结构编组为JSON?(How to not marshal an empty struct into JSON with Go?)
    问题 我有一个这样的结构: type Result struct { Data MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` } 但是,即使MyStruct实例完全为空(意味着所有值都是默认值),它也会被序列化为: "data":{} 我知道encoding / json文档指定“空”字段为: false,0,任何nil指针或接口值以及任何长度为零的数组,切片,映射或字符串 但不考虑具有所有空/默认值的结构。 它的所有字段也都标有omitempty ,但这没有效果。 如何获取JSON包以不封送我的字段为空结构? 回答1 正如文档所说,“任何零指针”。 -使结构成为指针。 指针具有明显的“空”值: nil 。 修复-使用结构指针字段定义类型: type Result struct { Data *MyStruct `json:"data,omitempty"` Status string `json:"status,omitempty"` Reason string `json:"reason,omitempty"` } 然后是一个像这样的值: result := Result{} 将封送为: {} 说明
  • 如果一个结构不能继承另一个类或结构,为什么 Int32 有一个 ToString() 方法? [复制](If a struct cannot inherit another class or struct, why does Int32 have a ToString() method? [duplicate])
    问题 这个问题在这里已经有了答案: ValueTypes 如何从 Object (ReferenceType) 派生并仍然是 ValueTypes? (6 个回答) 7年前关闭。 int a = 2; Console.WriteLine(a.ToString()); // displays 2 // definition of ToString() here - public override string ToString(); 现在,这里是我的一些理解: .net 中的所有类都有一个ToString()方法,该方法继承自Object类。 结构不能从类或其他结构派生。 int是一个Int32类型的结构,它从它实现的接口中获取几个ToString() [With Parameters] 方法。 struct Int32还有一个ToString() [没有参数] 函数 根据 http://msdn.microsoft.com/en-us/library/system.int32.tostring.aspx, struct Int32 覆盖 ValueType.ToString() 方法 如果结构不能继承某个类或结构,你能解释一下这个ToString()方法如何用于Int32吗? 回答1 如果结构不能继承某个类或结构, 这不是真的。 所有结构(以及内置值类型,如System.Int32
  • 如何以一种好的方式使用SQL NULL值和JSON?(How can I work with SQL NULL values and JSON in a good way?)
    问题 像Int64和String这样的Go类型不能存储null值,因此我发现可以为此使用sql.NullInt64和sql.NullString。 但是,当我在Struct中使用它们,并使用json包从Struct生成JSON时,格式与使用常规Int64和String类型时的格式不同。 JSON具有附加级别,因为sql.Null ***也是Struct。 有没有很好的解决方法,还是应该在我的SQL数据库中不使用NULL? 回答1 诸如sql.NullInt64类的类型sql.NullInt64 JSON封送或sql.NullInt64实施任何特殊处理,因此适用默认规则。 由于类型是结构,因此将其编组为对象,并将其字段作为属性。 解决此问题的一种方法是创建自己的类型,以实现json.Marshaller / json.Unmarshaler接口。 通过嵌入sql.NullInt64类型,我们免费获得了SQL方法。 像这样的东西: type JsonNullInt64 struct { sql.NullInt64 } func (v JsonNullInt64) MarshalJSON() ([]byte, error) { if v.Valid { return json.Marshal(v.Int64) } else { return json.Marshal(nil) } }
  • 封送处理-这是什么,为什么我们需要它?(Marshaling – what is it and why do we need it?)
    问题 什么是编组,为什么我们需要它? 我发现很难相信我无法通过C#到C的网络发送int ,而不得不进行封送处理。 为什么C#不能只用开始和结束信号发送32位,告诉C代码它已经接收到一个int ? 如果有任何很好的教程或网站介绍为什么我们需要编组以及如何使用它,那就太好了。 回答1 由于不同的语言和环境具有不同的调用约定,不同的布局约定,图元的不同的尺寸(参见char在C#和char中C),不同的对象创建/销毁公约,和不同的设计准则。 您需要一种方法来将这些东西从管理土地中带入某个地方,在该地方非管理土地可以看到和理解它,反之亦然。 这就是编组的目的。 回答2 .NET代码(C#,VB)被称为“托管”,因为它是由CLR(公共语言运行时)“托管”的 如果您使用C或C ++或汇编器编写代码,由于不涉及CLR,因此全部称为“非托管”。 您负责所有内存分配/取消分配。 封送处理是托管代码和非托管代码之间的过程。 它是CLR提供的最重要的服务之一。 回答3 理想情况下,将int编组就是您所说的:将内存从CLR的托管堆栈复制到C代码可以看到它的某个位置。 编组字符串,对象,数组和其他类型是困难的事情。 但是P / Invoke互操作层几乎可以为您处理所有这些事情。 回答4 正如Vinko在评论中所说,您可以传递原始类型而无需任何特殊的编组。 这些被称为“可迁移”类型,包括字节,短型,整型
  • 论文研读-图嵌入-2018综述
    图嵌入综述论文研读 一、论文概述1 文章摘要2 关键词3 文章脉络4 文章贡献 二、图嵌入是什么1 简单概念2 形式化定义3 图嵌入发展 三、图嵌入问题设置1 嵌入输入同构图异构图带辅助信息的图构造图 2 嵌入输出节点嵌入边嵌入混合嵌入全图嵌入 四、图嵌入技术五、图嵌入应用1 节点相关的应用节点分类节点聚类节点的推荐/检索/排名 2 边相关的应用链接预测三元组分类 3 图相关的应用图分类可视化 4 其他应用知识图谱相关多媒体网络相关信息传播相关社交网络对齐图像相关 六、未来研究方向1 计算2 问题设置3 技术4 应用场景 七、总结(收获)八、感受 一、论文概述 这是一篇2018年发表在IEEE知识与数据工程汇刊上的图嵌入的综述,论文题目为A Comprehensive Survey of Graph Embedding:Problems, Techniques, and Applications。如题目所示,主要对图嵌入问题中存在的挑战、现有的一些技术和应用场景进行了总结。 1 文章摘要 图是一种重要的数据表示形式,它出现在各种现实场景中。有效的图分析可以让用户更深入地了解数据背后的内容,从而受益于许多有用的应用,如节点分类、节点推荐、链接预测等。然而,大多数图分析方法都有很高的计算和空间成本。图嵌入是解决图分析问题的一种有效而高效的方法
  • 为什么我们需要序列化对象以将一个活动传递给 Android 中的另一个活动(Why we need to serializable object for passing one activity to another activity in Android)
    问题 谁能告诉我们为什么我们需要serializable对象来将一个活动传递给 android 中的另一个活动? Android 遵循 Java 语法。 在java中,我们可以将对象传递给另一个类而无需序列化。 谢谢 回答1 在传递参数(对象类型)的普通 java 程序中,是为对象创建一个新的处理程序并提供给另一个方法(在常规词中按值传递引用)。 但是当它出现在 android 中时,将对象引用从一个活动传递到另一个活动,它们的状态必须被持久化,这是一个令人头疼的问题。 您可以做的一种方法是在第一个活动中创建一个静态对象并从第二个活动中访问,尽管这似乎是最简单的方法,但不能保证系统在内存中维护活动。 因此,第二个活动可能会丢失对象引用。 其他方式,也是最推荐的方式是序列化(有点扁平化对象)对象并以额外的意图传递。 在android中有两种序列化方式。 实现java的可序列化接口实现android的parcelable接口 但是,在 android 上,使用可序列化会严重影响性能,解决方案是使用 Parcelable。 您可以在此处找到有关 android parsable 实现的非常好的教程和说明。 回答2 在得到答案之前,我们需要了解以下概念: Android 使用Binder进行进程间进程。 即使是简单的应用程序也需要它,因为操作系统和应用程序在不同的进程中运行。 编组
  • JPA/Hibernate - 嵌入属性(JPA/Hibernate - Embedding an Attribute)
    问题 我在映射类的嵌入属性时遇到问题。 我创建了一些类似于我试图做的说明的类。 基本上,我有一个使用继承的@Embeddable 类层次结构。 顶级类“Part Number”只有一个属性,扩展类没有向“Part Number”类添加任何属性,它们只添加了一些验证/逻辑。 这就是我的意思: 部分 @Entity @Table(name="PART") public class Part { private Integer id; private String name; private PartNumber partNumber; @Id @GeneratedValue(strategy=GenerationType.SEQUENCE) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(name="PART_NAME") public String getName() { return name; } public void setName(String name) { this.name = name; } @Embedded public PartNumber getPartNumber() { return partNumber; }
  • JSON和处理未导出的字段(JSON and dealing with unexported fields)
    问题 是否存在技术原因,为什么编码/ json不包含未导出的字段? 如果不是这样,这是一个任意决定,即使未导出,是否还会有其他后门选项(例如“ +”)包括在内? 要求导出客户端代码以获取此功能感到很不幸,尤其是在小写形式提供封装或封送结构的决定比其设计晚得多的情况下。 人们如何处理这个问题? 只是出口一切? 另外,不导出字段名称会使遵循建议的惯用法变得困难。 我认为,如果结构X具有字段Y,则不能具有访问器方法Y()。 如果要提供对Y的接口访问权限,则必须为getter命名一个新名称,并且根据http://golang.org/doc/effective_go.html#Getters,无论您得到什么,都是不习惯的 回答1 有技术原因。 除非已导出,否则json库无权使用反射来查看字段。 包只能查看其自己包中类型的未导出字段 为了解决您的问题,您可以做的是使用导出的字段创建未导出的类型。 如果将Json毫无问题地传递给未导出的类型,它将解组为未导出的类型,但是它不会显示在API文档中。 然后,您可以创建嵌入未导出类型的导出类型。 然后,此导出的类型将需要方法来实现json.Marshaler和json.Unmarshaler接口。 注意:所有代码都未经测试,甚至可能无法编译。 type jsonData struct { Field1 string Field2 string }
  • 《Go语言圣经》学习笔记 第四章 复合数据类型
    《Go语言圣经》学习笔记 第四章 复合数据类型 目录 数组SliceMap结构体JSON文本和HTML模板 注:学习《Go语言圣经》笔记,PDF点击下载,建议看书。 Go语言小白学习笔记,书上的内容照搬,大佬看了勿喷,以后熟悉了会总结成自己的读书笔记。 在第三章我们讨论了基本数据类型, 它们可以用于构建程序中数据结构, 是Go语言的世界的原子。 在本章, 我们将讨论复合数据类型, 它是以不同的方式组合基本类型可以构造出来的复合数据类型。 我们主要讨论四种类型——数组、 slice、 map和结构体——同时在本章的最后, 我们将演示如何使用结构体来解码和编码到对应JSON格式的数据, 并且通过结合使用模板来生成HTML页面。数组和结构体是聚合类型; 它们的值由许多元素或成员字段的值组成。 数组是由同构的元素组成——每个数组元素都是完全相同的类型——结构体则是由异构的元素组成的。 数组和结构体都是有固定内存大小的数据结构。 相比之下, slice和map则是动态的数据结构, 它们将根据需要动态增长。 1. 数组 数组是一个由固定长度的特定类型元素组成的序列, 一个数组可以由零个或多个元素组成。因为数组的长度是固定的, 因此在Go语言中很少直接使用数组。 和数组对应的类型是Slice( 切片) , 它是可以增长和收缩动态序列, slice功能也更灵活,
  • 什么是对象编组?(What is object marshalling?)
    问题 我听说过这个概念经常使用,但是我对它的概念并不十分了解。 回答1 将内存中的对象转换为可以写入磁盘或通过电线发送的格式等。 维基百科的描述。 回答2 抱歉,维基百科对此很清楚。 在计算机科学中,编组(类似于序列化)是将对象的内存表示形式转换为适合存储或传输的数据格式的过程。 通常在必须在计算机程序的不同部分之间或从一个程序到另一个程序之间移动数据时使用。 http://en.wikipedia.org/wiki/Marshalling_(computer_science) 回答3 人们已经非常清楚地定义了编组,所以我将跳过该定义并跳到一个示例。 远程过程调用使用编组。 调用远程功能时,必须将参数编组为某种标准格式,以便可以在网络上进行传输。 回答4 编组是将对象的内存表示形式转换为可以存储或传输的数据格式的过程。 这也称为序列化(尽管在某些情况下可能有所不同)。 对象的内存表示形式可以二进制或XML的形式存储或适合存储和/或传输的任何格式,以允许您解组并将原始对象取回的方式存储。 以用法为例,如果您有一些包含客户端和服务器组件的在线游戏,并且想要将包含玩家统计信息和世界坐标的玩家对象从客户端发送到服务器(或者相反),则可以简单地编组它在客户端,通过网络发送,然后在另一端解组,它对于服务器来说就好像对象是在服务器本身上创建的一样。 这是一个红宝石示例: srcplayer =
  • 系统架构设计笔记(1)—— 操作系统的类型与结构
    掌握操作系统原理的关键:一个观点、两条线索。 一个观点:以资源管理的观点来定义操作系统;从资源管理的角度看,操作系统主要是对处理器、存储器、文件、设备和作业进行管理。两条线索:如何管理计算机各类资源、控制程序的执行。 现在讲讲操作系统的类型与结构。 操作系统(Operating System,OS)是计算机系统中的核心系统软件,负责管理和控制计算机系统中的硬件和软件资源,合理地组织计算机工作流程和有效地利用资源,在计算机与用户之间起接口的作用。 对象接口形式用户命令、菜单、窗口等。应用程序API。 其他系统软件属于第二层,如编辑程序、汇编程序 、 编译程序和数据库管理系统等系统软件。这些软件工作于操作系统之上,服务于应用软件,所以有别于应用软件。 1操作系统类型 按使用环境和对作业的处理方式,操作系统可分为批处理操作系统 、 分时操作系统 、 实时操作系统 、 网络操作系统和分布式操作系统 。后来又加入了嵌入式与微内核操作系统。 批处理操作系统把用户提交的作业分类,把一批中的作业编成一个作业执行序列。批处理又可分为联机批处理和脱机批处理。批处理系统的主要特征有 : 用户脱机使用计算机 、 成批处理 、 多道程序运行。 分时操作系统采用分时技术,使多个用户同时以会话方式控制自己程序的运行,每个用户都感到似乎各自有一台独立的 、支持自己请求服务的系统
  • 用于Web服务的SOAP还是REST? [关闭](SOAP or REST for Web Services? [closed])
    问题 关门了。 这个问题是基于意见的。 它当前不接受答案。 想要改善这个问题吗? 更新问题,以便可以通过编辑此帖子以事实和引用的形式回答。 4年前关闭。 改善这个问题 REST是进行Web服务的更好方法还是SOAP? 还是针对不同问题的不同工具? 还是这是一个细微的问题-也就是说,在某些领域中,一个领域比另一个领域要好一些吗? 我特别希望了解有关这些概念及其与PHP宇宙以及现代高端Web应用程序的关系的信息。 回答1 当我在惠普工作时,我根据最初的规范构建了第一批SOAP服务器,包括代码生成和WSDL生成。 我不建议对任何东西使用SOAP。 首字母缩写词“ SOAP”是一个谎言。 它不是简单的,也不是面向对象的,它没有定义访问规则。 可以说,它是一个协议。 这是Don Box有史以来最糟糕的规格,这确实是一项壮举,因为他是实施“ COM”的人。 在SOAP中,没有什么可以用REST进行传输,JSON,XML甚至纯文本进行数据表示的方法有用。 为了传输安全,您可以使用https。 对于身份验证,请使用基本身份验证。 对于会话,有cookie。 REST版本将更简单,更清晰,运行速度更快并且使用的带宽更少。 XML-RPC清楚地定义了请求,响应和错误协议,并且对于大多数语言都有不错的库。 但是,XML比许多任务所需的重。 回答2 REST是一种体系结构,SOAP是一种协议。
  • C ++中的struct和class有什么区别?(What are the differences between struct and class in C++?)
    问题 已经在C#/。Net上下文中提出了此问题。 现在,我想学习C ++中的结构和类之间的区别。 请讨论技术差异以及在OO设计中选择一个或另一个的原因。 我将从一个明显的区别开始: 如果您未指定public:或private: :,则结构的成员默认情况下为public;否则,默认为public。 默认情况下,类的成员是私有的。 我确信在C ++规范的晦涩之处可以找到其他差异。 回答1 您会忘记类和结构之间的棘手的第二个区别。 符合标准(C ++ 98到C ++ 11中的第11.2.2节): 在不存在访问说明符为基类的,当派生的类声明struct和私人假设在类被声明的类假定公众。 出于完整性的考虑,在(11.2)中定义了class和struct之间更广为人知的区别: 默认情况下,用关键字class定义的类的成员是私有的。 默认情况下,使用关键字struct或union定义的类的成员是公共的。 附加区别:关键字class可用于声明模板参数,而struct关键字则不能如此使用。 回答2 引用C ++常见问题解答, [7.8]关键字struct和class有什么区别? 默认情况下,结构的成员和基类是公共的,而在类中,它们的缺省是私有的。 注意:您应该将基类显式设置为公共,私有或受保护,而不要依赖默认值。 结构和类在功能上是等效的。 好吧,足够的干净利落的技术演讲。 从情感上讲
  • 我应该什么时候使用 RequestFactory 和 GWT-RPC?(When should I use RequestFactory vs GWT-RPC?)
    问题 我想弄清楚是否应该将我的 gwt-rpc 调用迁移到新的 GWT2.1 RequestFactory cals。 谷歌文档模糊地提到 RequestFactory 是一种更好的“面向数据的服务”的客户端-服务器通信方法 我可以从文档中提炼出的是,有一个新的 Proxy 类可以简化通信(您不会来回传递实际实体,而只会传递代理,因此重量更轻且更易于管理) 这是重点还是我在大局中遗漏了其他东西? 回答1 GWT RPC 和 RequestFactory 最大的区别在于 RPC 系统是“RPC-by-concrete-type”,而 RequestFactory 是“RPC-by-interface”。 RPC 更易于上手,因为您编写的代码行更少,并且在客户端和服务器上使用相同的类。 您可能会创建一个带有一堆 getter 和 setter 的Person类,也许还有一些简单的业务逻辑,以便进一步对Person对象中的数据进行切片和切块。 这非常有效,直到您最终想要在您的类中包含特定于服务器的、非 GWT 兼容的代码。 因为 RPC 系统基于在客户端和服务器上具有相同的具体类型,所以您可能会遇到基于 GWT 客户端功能的复杂性墙。 为了避免使用不兼容的代码,许多用户最终创建了一个对等的PersonDTO ,它PersonDTO了服务器上使用的真实Person对象。
  • JSON和协议缓冲区之间是否存在标准映射?(Is there a standard mapping between JSON and Protocol Buffers?)
    问题 从公告博客文章的评论中: 关于JSON:JSON的结构类似于协议缓冲区,但是协议缓冲区二进制格式仍然更小且编码更快。 但是,JSON为协议缓冲区提供了一种出色的文本编码-编写编码器/解码器是很简单的,该编码器/解码器使用protobuf反射将任意协议消息与JSON相互转换。 这是与AJAX应用程序通信的好方法,因为让用户在访问您的页面时下载完整的protobuf解码器可能太多了。 编写一个映射可能是微不足道的,但是在两者之间是否有一个单独的“显而易见的”映射,任何两个独立的开发团队都会自然地适应于此? 如果两个产品支持PB数据并且因为它们共享相同的.proto规范而可以互操作,我想知道如果它们独立引入相同规范的JSON反射,它们是否仍然可以互操作。 可能会做出一些任意决定,例如枚举值应该用字符串(对于人类来说是典型的JSON可读)还是整数值来表示? 那么,是否存在已建立的映射以及用于从.proto规范生成JSON编码器/解码器的任何开源实现? 回答1 是的,自协议缓冲区版本3.0.0(2016年7月28日发布)以来,存在发行说明中提到的“ JSON中定义明确的编码,可以替代二进制原型编码” https://github.com/google/protobuf/releases/tag/v3.0.0 回答2 可能对您有所帮助http://code.google.com/p
  • C#P /调用:包含函数指针的编组结构(C# P/Invoke: Marshalling structures containing function pointers)
    问题 很抱歉,下面的详细介绍。 我需要比我更了解P / Invoke内部知识的人提供见解。 这是我编组包含从C到C#的函数指针的结构的方式。 我想知道这是否是最干净和/或最有效的方法。 我正在与用C编码的本机DLL交互,该DLL提供以下入口点: void* getInterface(int id); 您必须传递getInterface(int)以下枚举值之一: enum INTERFACES { FOO, BAR }; 它返回一个指向包含函数指针的结构的指针,如: typedef struct IFOO { void (*method1)(void* self, int a, float b); void (*method2)(void* self, int a, float b, int c); } IFoo; 这是在C中使用它的方式: IFoo* interface = (IFoo*)getInterface(FOO); interface->method1(obj, 0, 1.0f); // where obj is an instance of an object // implementing the IFoo interface. 在C#中,我有一个Library类,该类使用P / Invoke映射getInterface(int)入口点。 class Library
  • 静态分配不透明数据类型(Static allocation of opaque data types)
    问题 在嵌入式系统上编程时,经常绝对不允许使用malloc()。 在大多数情况下,我都能够很好地解决这一问题,但是有一件事让我感到恼火:它使我无法使用所谓的“不透明类型”来隐藏数据。 通常我会做这样的事情: // In file module.h typedef struct handle_t handle_t; handle_t *create_handle(); void operation_on_handle(handle_t *handle, int an_argument); void another_operation_on_handle(handle_t *handle, char etcetera); void close_handle(handle_t *handle); // In file module.c struct handle_t { int foo; void *something; int another_implementation_detail; }; handle_t *create_handle() { handle_t *handle = malloc(sizeof(struct handle_t)); // other initialization return handle; } 随您去:create_handle()执行malloc
  • 我的结构没有编组到json中[重复](My structures are not marshalling into json [duplicate])
    问题 这个问题已经在这里有了答案: json.Marshal(struct)返回“ {}” (3个答案) 1年前关闭。 我在Mac OS X 10.8.2上使用Go 1.0.3,并且正在尝试使用json包,试图将结构编组为json,但是我一直得到一个空的{} json对象。 err值为nil,所以根据json.Marshal函数,没有什么错,并且该结构是正确的。 为什么会这样呢? package main import ( "encoding/json" "fmt" ) type Address struct { street string extended string city string state string zip string } type Name struct { first string middle string last string } type Person struct { name Name age int address Address phone string } func main() { myname := Name{"Alfred", "H", "Eigenface"} myaddr := Address{"42 Place Rd", "Unit 2i", "Placeton", "ST", "00921"} me := Person
  • * .tlb文件在运行时是否曾经使用过?(Are *.tlb files ever used at runtime?)
    问题 我正在开发一种通过COM互操作公开一些.NET API的产品。 作为构建的一部分,我们为所有此类程序集生成* .tlb文件,并将其作为单独的SDK软件包的一部分提供。 我们的客户可以在产品之上安装SDK,并创建使用我们的COM API的应用程序。 我们是否需要将这些* .tlb文件发送并注册到产品本身? 是否存在在运行时需要* .tlb并执行针对它们编码的第三方库的情况? 如果您回答“是”,请说明其工作原理。 我在互联网上看到很多评论,这些评论说我必须进行交付和注册,但是我没有找到能清楚说明为什么应该这样做的评论。 这使我怀疑这是真的。 回答1 是的,那是可能的。 尤其是在.NET的情况下,您不应忽略注册类型库,因为您无法预测客户端代码将如何使用服务器。 它们不是特别常见,但是有两种情况: 当客户端代码调用您的[ComVisible]方法,并且该调用越过单元边界时。 公寓是一个有点模糊的COM概念,您必须了解STA和MTA线程之间的区别。 保持简单:从另一个线程,另一个进程或另一个计算机进行调用时,通常会跨越一个公寓边界。 COM需要帮助找出如何将调用的参数序列化为IPC数据包,并且这需要知道参数的类型。 COM中没有反射的概念,因此无法轻松自动完成。 需要一个单独的DLL来实现代理和存根,几乎总是从IDL文件中生成。 在.NET中很难做到这一点