为什么我会收到“Composite Literal Uses Unkeyed”错误?

huangapple go评论86阅读模式
英文:

Why do I get "Composite Literal Uses Unkeyed" error?

问题

我对Go相对较新,正在构建一个请求解码器。请求以JSON格式传入,我们将其解码为map[string]interface{}。然后,我们将该对象数据传入以解码为我们自己的ProcessRequest结构。正如我所说,我是新手,所以我正在重用一些由之前的开发人员编写的代码中的类似部分的逻辑。基本上,我们正在检查map中是否有必要的部分,然后设置并返回这些部分。有人能解释一下为什么我会得到这个错误吗?我是否需要将项目设置到不再有任何嵌套的基本结构中?有没有更好的方法来实现我想要的效果?这是代码和相关结构。它在返回model.ProcessRequest的地方突出显示错误。谢谢!

type ProcessRequest struct {
	RequestID string
	Message   *message.Message
	Rule      *Rule
	Options   *ProcessOptions
	//TODO: Context EvaluatorContext
	//TODO: Links
}

type Message struct {
	ID         int
	Key        string
	Source     string
	Headers    *HeaderSet
	Categories *CategorySet
	Properties *PropertySet
	Streams    *StreamSet
}

type RuleAction struct {
	Name       string
	Expression map[string]interface{}
}

type RuleLink struct {
	LinkID       int
	Condition    map[string]interface{}
	TargetRuleID int
}

type Rule struct {
	Name    string
	Code    string
	Actions []RuleAction
	Links   []RuleLink
}
type object = map[string]interface{}

func DecodeProcessRequest(dataObject map[string]interface{}) (*model.ProcessRequest, error) {
	var (
		requestID string
		message   *message.Message
		rule      *model.Rule
		options   *model.ProcessOptions
		err       error
	)

	if reqIDSrc, ok := dataObject["requestId"]; ok {
		if requestID, err = converter.ToString(reqIDSrc); err != nil {
			return nil, errors.Wrapf(err, "Error reading property 'requestID'")
		}
		if requestID == "" {
			return nil, errors.Errorf("Property 'requestID' is an empty string")
		}
	} else {
		return nil, errors.Errorf("Missing required property 'requestID'")
	}

	if messageSrc, ok := dataObject["message"]; ok {
		messageData, ok := messageSrc.(object)
		if !ok {
			return nil, errors.Errorf("Error reading property 'message': Value is not an object")
		}
		if message, err = DecodeMessage(messageData); err != nil {
			return nil, errors.Wrapf(err, "Error reading property 'message'")
		}
	} else {
		return nil, errors.Errorf("Missing required property 'message'")
	}

	if ruleSrc, ok := dataObject["rule"]; ok {
		ruleObj, ok := ruleSrc.(object)
		if !ok {
			return nil, errors.Errorf("Error reading property 'rule': Value is not an object")
		}
		if rule, err = DecodeRule(ruleObj); err != nil {
			return nil, errors.Wrapf(err, "Error reading 'rule' during decoding")
		}
	} else {
		return nil, errors.Errorf("Missing required property 'requestID'")
	}
	// Parse plain object to a Message struct
	return &model.ProcessRequest{
		requestID,
		message,
		rule,
		options,
	}, nil

}
英文:

I'm relatively new to Go and am working on building out a request decoder. The request comes in JSON format and we decode that to a map[string]interface{}. We then pass that object data in to be decoded to our own ProcessRequest struct. As I said I'm new so I am reusing some logic in similar parts of the code wrote by previous developers. Essentially we are checking the map for the necessary pieces and then setting and returning those. Can someone explain to me why I am getting the titled error? Would I have to set the items all the way down to base structs that no longer have any nested? Is there a better way to accomplish what I want? Here is the code and the related structs. It is highlighting the error on the return of the model.ProcessRequest. TYIA

type ProcessRequest struct {
RequestID string
Message   *message.Message
Rule      *Rule
Options   *ProcessOptions
//TODO: Context EvaluatorContext
//TODO: Links
}
type Message struct {
ID         int
Key        string
Source     string
Headers    *HeaderSet
Categories *CategorySet
Properties *PropertySet
Streams    *StreamSet
}
type RuleAction struct {
Name       string
Expression map[string]interface{}
}
type RuleLink struct {
LinkID       int
Condition    map[string]interface{}
TargetRuleID int
}
type Rule struct {
Name    string
Code    string
Actions []RuleAction
Links   []RuleLink
}
type object = map[string]interface{}
func DecodeProcessRequest(dataObject map[string]interface{}) (*model.ProcessRequest, error) {
var (
requestID string
message   *message.Message
rule      *model.Rule
options   *model.ProcessOptions
err       error
)
if reqIDSrc, ok := dataObject["requestId"]; ok {
if requestID, err = converter.ToString(reqIDSrc); err != nil {
return nil, errors.Wrapf(err, "Error reading property 'requestID'")
}
if requestID == "" {
return nil, errors.Errorf("Property 'requestID' is an empty string")
}
} else {
return nil, errors.Errorf("Missing required property 'requestID'")
}
if messageSrc, ok := dataObject["message"]; ok {
messageData, ok := messageSrc.(object)
if !ok {
return nil, errors.Errorf("Error reading property 'message': Value is not an object")
}
if message, err = DecodeMessage(messageData); err != nil {
return nil, errors.Wrapf(err, "Error reading property 'message'")
}
} else {
return nil, errors.Errorf("Missing required property 'message'")
}
if ruleSrc, ok := dataObject["rule"]; ok {
ruleObj, ok := ruleSrc.(object)
if !ok {
return nil, errors.Errorf("Error reading property 'rule': Value is not an object")
}
if rule, err = DecodeRule(ruleObj); err != nil {
return nil, errors.Wrapf(err, "Error reading 'rule' during decoding")
}
} else {
return nil, errors.Errorf("Missing required property 'requestID'")
}
// Parse plain object to a Message struct
return &model.ProcessRequest{
requestID,
message,
rule,
options,
}, nil
}

答案1

得分: -1

super这个评论中说:

> 一般来说,警告表示你应该优先使用语法ProcessRequest{ RequestID: requestID, ... },即使用命名的键而不是无键的值。

这对我有用。还有kostix这个评论中的解释真的很有帮助。

>基本上,如果你使用"无键"的方式定义结构体字面量,那么你的定义的含义取决于底层类型字段的布局方式。现在假设你的类型有三个按照某种顺序排列的string类型字段。然后在后续的几次迭代中,某个程序员将第二个字段移动到第一个位置——你的字面量仍然可以编译通过,但在运行时将定义一个完全不同的值。

英文:

super said in this comment:

> In general, the warning says that you should prefer to use the syntax ProcessRequest{ RequestID: requestID, ... }. Naming the keys instead of unkeyed values.

That worked for me. Also the explanation by kostix in this comment really helped.

>Basically the idea is that if you use "unkeyed" way of defining struct literals, the meaning of your definitions depends on the way the fields of the underlying type are layed out. Now consider that your type has three fields of type string in a certain order. Now a couple of iterations down the road some programmer moves the second field to the 1st position—your literal will still compile but will end up defining a completely different value at runtime.

huangapple
  • 本文由 发表于 2022年3月16日 22:06:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/71498491.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定