Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

interface for fields in golang

Tags:

inheritance

go

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

type uploadResult struct {
  Filename string `json:"filename"`
  Code string `json:"code"`
  Reason string `json:"reason"`
}

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):

type apiResult interface {
  Code string `json:"code"`
  Reason string `json:"reason"`
}

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

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

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

Best regards

like image 239
Atmocreations Avatar asked Mar 12 '15 15:03

Atmocreations


2 Answers

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-

type apiResult struct {
  Code string `json:"code"`
  Reason string `json:"reason"`
}

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

type uploadResult struct {
  Filename string `json:"filename"`
  apiResult // <-- embedded
}

func main() {
  var ul uploadResult
  ul.Code = "...some code..."
  ul.Reason = "The description"
  ul.Filename = "foo.txt"

  failExit(ul.apiResult)
}

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

like image 131
Lye Fish Avatar answered Sep 22 '22 02:09

Lye Fish


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.

type APIResult struct {
    Code   string `json:"code"`
    Reason string `json:"reason"`
}

type UploadResult struct {
  Filename string `json:"filename"`
  APIResult
}

func failExit(result APIResult) {
  fmt.Println(result.Reason)
}

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

like image 31
Leo Correa Avatar answered Sep 20 '22 02:09

Leo Correa