我想创建一个名为merge()
的函数,该函数接受同一结构但 any 结构的两个值,并返回这两个结构的合并值。
我希望第一个值优先。例如,如果有两个结构a
和b
,则在调用merge(a,b)
之后,如果同时存在a
和b
都包含的字段,我希望它具有该给定字段的a
的值。
实现此目标的最佳方法是什么? https://play.golang.org/p/7s9PWx26gfz
type cat struct {
name string
color string
age int
}
type book struct {
title string
author string
}
func main() {
c1 := cat{
name: "Oscar",
color: "",
age: 3,
}
c2 := cat{
name: "",
color: "orange",
age: 2,
}
c3 := merge(c1, c2)
// want: c3 = cat{
// name: "Oscar",
// color: "orange",
// age: 3,
// }
// another case...
b1 := book{
title: "Lord of the Rings",
author: "John Smith",
}
b2 := book{
title: "Harry Potter",
author: "",
}
b3 := merge(b1, b2)
// want: b3 = book{
// title: "Lord of the Rings",
// author: "John Smith",
// }
}
这是我到目前为止所拥有的:
// merges two structs, where a's values take precendence over b's values (a's values will be kept over b's if each field has a value)
func merge(a, b interface{}) (*interface{}, error) {
var result interface{}
aFields := reflect.Fields(a)
bFields := reflect.Fields(b)
if !reflect.DeepEqual(aFields, bFields) {
return &result, errors.New("cannot merge structs of different struct types")
}
aValOf := reflect.ValueOf(a)
bValOf := reflect.ValueOf(b)
resultValOf := reflect.ValueOf(result)
aValues := make([]interface{}, aValOf.NumField())
resultValues := make([]interface{}, resultValOf.NumField())
for i := 0; i < aValOf.NumField(); i++ {
if reflect.ValueOf(aValues[i]).IsNil() {
resultValues[i] = bValOf.Field(i).Interface()
break
}
resultValues[i] = aValOf.Field(i).Interface()
}
return &result, nil
}
答案 0 :(得分:1)
对目标结构中的字段使用自定义类型。
int delayVal = 100;
char action = "n";
void setup() {
// put your setup code here, to run once:
pinMode(8,OUTPUT);
pinMode(7,OUTPUT);
Serial.begin(9600);
delay(100);
digitalWrite(8,HIGH);
digitalWrite(7,HIGH);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() > 0){
action = Serial.read();
newAction();
}
}
void newAction(){
if(action == 'o'){
openRelays();
}else if(action == 'c'){
closeRelays();
}else if(action == 'd'){
bool canContinue = false;
while(!canContinue){
if(Serial.available() > 0){
String val = Serial.readString();
delayVal = val.toInt();
canContinue = true;
}
}
}else{
Serial.println("No hay nada");
}
}
void openRelays(){
digitalWrite(8,LOW);
digitalWrite(7,LOW);
}
void closeRelays(){
digitalWrite(8,HIGH);
delay(delayVal);
digitalWrite(7,HIGH);
}
对每种自定义类型实施UnMarshalJSON,以便它们仅对空的目标值进行解组。
type firstString string
type firstInt int
type cat struct {
Name firstString
Color firstString
Age firstInt
}
type book struct {
Title firstString
Author firstString
}
如果您的数据是通过JSON传递的,则可以避免使用merge函数;只需取消将传入的JSON编组到同一结构即可。如果您的数据已经在不同的结构中,则可以在合并函数中使用JSON作为中介,以抽象化示例中所有的反映。
func (fs *firstString) UnmarshalJSON(bytes []byte) error {
if len(*fs) > 0 {
return nil
}
var s string
err := json.Unmarshal(bytes, &s)
if err != nil {
return err
}
*fs = firstString(s)
return nil
}
func (fi *firstInt) UnmarshalJSON(bytes []byte) error {
if *fi != 0 {
return nil
}
var i int
err := json.Unmarshal(bytes, &i)
if err != nil {
return err
}
*fi = firstInt(i)
return nil
}
在一个有效的示例中:https://play.golang.org/p/5YO2HCi8f0N
答案 1 :(得分:0)
检查此软件包https://github.com/imdario/mergo
示例代码:
package main
import (
"fmt"
"github.com/imdario/mergo"
)
type Foo struct {
A string
B int64
}
func main() {
src := Foo{
A: "one",
B: 2,
}
dest := Foo{
A: "two",
}
mergo.Merge(&dest, src)
fmt.Println(dest)
// Will print
// {two 2}
}