Golang中的字段接口

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

interface for fields in golang

问题

假设我有一个用作上传结果的结构体:

  1. type uploadResult struct {
  2. Filename string `json:"filename"`
  3. Code string `json:"code"`
  4. Reason string `json:"reason"`
  5. }

还会有其他类似的结构体,它们都有一个名为Code和另一个名为Reason的字段。因此,有一个类似于公共接口的东西会很有意思(伪代码;这个是无法工作的):

  1. type apiResult interface {
  2. GetCode() string
  3. GetReason() string
  4. }

因为我想调用一个函数来提取一些公共字段,但只提取那些公共字段:

  1. func failExit(result apiResult) {
  2. fmt.Println(result.GetReason())
  3. }

那么,我应该如何重写它以达到我期望的效果呢?

最好的问候。

英文:

Let's say I have a struct which should be used as a result for an upload:

  1. type uploadResult struct {
  2. Filename string `json:"filename"`
  3. Code string `json:"code"`
  4. Reason string `json:"reason"`
  5. }

There will be other structs like this one, both having a field Code and another one called Reason. It would therefore be interesting to have something like a common interface (pseudo-go-code; this one doesn't work):

  1. type apiResult interface {
  2. Code string `json:"code"`
  3. Reason string `json:"reason"`
  4. }

Because I would like to call a function which extracts some common fields, but only those that are common:

  1. func failExit(result apiResult) {
  2. fmt.Println(result.Reason)
  3. }

So how would I rewrite it so that it does what I'm expecting?

Best regards

答案1

得分: 11

你只需要在特定的结构体中嵌入具有共同字段的结构体即可。

  1. type apiResult struct {
  2. Code string `json:"code"`
  3. Reason string `json:"reason"`
  4. }
  5. func failExit(result apiResult) {
  6. fmt.Println(result.Reason)
  7. }
  8. type uploadResult struct {
  9. Filename string `json:"filename"`
  10. apiResult // <-- 嵌入
  11. }
  12. func main() {
  13. var ul uploadResult
  14. ul.Code = "...一些代码..."
  15. ul.Reason = "描述"
  16. ul.Filename = "foo.txt"
  17. failExit(ul.apiResult)
  18. }

所以在这种情况下,实际上不需要使用接口。只需将apiResult嵌入到需要它的结构体中即可。

英文:

You should just be able to embed a struct with the common fields in the specific structs.

Live demo: http://play.golang.org/p/7Ju-r-yE1-

  1. type apiResult struct {
  2. Code string `json:&quot;code&quot;`
  3. Reason string `json:&quot;reason&quot;`
  4. }
  5. func failExit(result apiResult) {
  6. fmt.Println(result.Reason)
  7. }
  8. type uploadResult struct {
  9. Filename string `json:&quot;filename&quot;`
  10. apiResult // &lt;-- embedded
  11. }
  12. func main() {
  13. var ul uploadResult
  14. ul.Code = &quot;...some code...&quot;
  15. ul.Reason = &quot;The description&quot;
  16. ul.Filename = &quot;foo.txt&quot;
  17. failExit(ul.apiResult)
  18. }

So there shouldn't really be any need for interfaces in this situation. Just embed the apiResult in whatever structs need it.

答案2

得分: 4

长话短说,Go语言的接口不允许声明字段,因为从概念上讲,它们处理的是行为而不是数据。字段是数据。

有几种方法可以实现你想要做的事情:

以下是一些处理方法的示例:

这个示例使用接口将APIResult字段作为apiResponse接口的一部分公开:
http://play.golang.org/p/ONLzvqlP5R

这个示例使用接口将APIResult作为包含它的任何Result结构的一部分公开:
http://play.golang.org/p/NzxPHhDls_

另外,你可以通过组合来解决这个问题,让APIResponse成为一个包含常见字段的结构体,然后任何需要这些字段的其他结构体都导出APIResponse结构体。

  1. type APIResult struct {
  2. Code string `json:"code"`
  3. Reason string `json:"reason"`
  4. }
  5. type UploadResult struct {
  6. Filename string `json:"filename"`
  7. APIResult
  8. }
  9. func failExit(result APIResult) {
  10. fmt.Println(result.Reason)
  11. }

http://play.golang.org/p/k85vTJoFRn

英文:

Long story short, Go interfaces don't allow fields to be declared because conceptually they deal with behavior not data. Fields are data.

There's a couple of ways to go about what you want to do:

Here's some examples on how to approach this:

This one uses an interface to expose the APIResult fields as part of the apiResponse interface:
http://play.golang.org/p/ONLzvqlP5R

This one uses an interface to expose the APIResult as part of any Result struct that contains one:
http://play.golang.org/p/NzxPHhDls_

On that note, you could solve this by using composition by having APIResponse be a struct that has the common fields and then any other struct that needs those fields exports the APIResponse struct.

  1. type APIResult struct {
  2. Code string `json:&quot;code&quot;`
  3. Reason string `json:&quot;reason&quot;`
  4. }
  5. type UploadResult struct {
  6. Filename string `json:&quot;filename&quot;`
  7. APIResult
  8. }
  9. func failExit(result APIResult) {
  10. fmt.Println(result.Reason)
  11. }

http://play.golang.org/p/k85vTJoFRn

huangapple
  • 本文由 发表于 2015年3月12日 23:44:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/29014215.html
匿名

发表评论

匿名网友

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

确定