golang: slice of struct != slice of interface it implements?












48















I have an interface Model, which is implemented by struct Person.



To get a model instance, I have the following helper functions:



func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}

func newPerson() *Person {
return &Person{}
}


The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).



When I attempted to do something similar for returning a slice of models, I get an error. Code:



func newModels(c string) Model {
switch c {
case "person":
return newPersons()
}
return nil
}

func newPersons() *Person {
var models Person
return &models
}


Go complains with: cannot use newPersons() (type Person) as type Model in return argument



My goal is to return a slice of whatever model type is requested (whether Person, FutureModel, Terminator2000, w/e). What am I missing, and how can I properly implement such a solution?










share|improve this question




















  • 3





    A slice is different from an array in Go. Since you were really talking about slices, I edited your post to reflect this.

    – Stephen Weinberg
    Oct 21 '12 at 4:15











  • Stephen, thanks, appreciated :-)

    – Jon L.
    Oct 21 '12 at 4:23











  • @JonL. Did you ever figure this out? I'm trying to do the same thing so that I don't have to repeat a ton of code for my /api/{collection}. I have it working for everything except for an index function that needs to read into a slice.

    – Derek Perkins
    Jul 25 '14 at 3:44













  • @DerekPerkins, I don't recall what I ended up doing here, and I haven't played w/ Go in awhile. Sorry I can't be of more assistance.

    – Jon L.
    Jul 30 '14 at 13:27











  • Contravariance (or is that covariance?) strikes again!

    – David
    Jul 19 '18 at 1:08
















48















I have an interface Model, which is implemented by struct Person.



To get a model instance, I have the following helper functions:



func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}

func newPerson() *Person {
return &Person{}
}


The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).



When I attempted to do something similar for returning a slice of models, I get an error. Code:



func newModels(c string) Model {
switch c {
case "person":
return newPersons()
}
return nil
}

func newPersons() *Person {
var models Person
return &models
}


Go complains with: cannot use newPersons() (type Person) as type Model in return argument



My goal is to return a slice of whatever model type is requested (whether Person, FutureModel, Terminator2000, w/e). What am I missing, and how can I properly implement such a solution?










share|improve this question




















  • 3





    A slice is different from an array in Go. Since you were really talking about slices, I edited your post to reflect this.

    – Stephen Weinberg
    Oct 21 '12 at 4:15











  • Stephen, thanks, appreciated :-)

    – Jon L.
    Oct 21 '12 at 4:23











  • @JonL. Did you ever figure this out? I'm trying to do the same thing so that I don't have to repeat a ton of code for my /api/{collection}. I have it working for everything except for an index function that needs to read into a slice.

    – Derek Perkins
    Jul 25 '14 at 3:44













  • @DerekPerkins, I don't recall what I ended up doing here, and I haven't played w/ Go in awhile. Sorry I can't be of more assistance.

    – Jon L.
    Jul 30 '14 at 13:27











  • Contravariance (or is that covariance?) strikes again!

    – David
    Jul 19 '18 at 1:08














48












48








48


17






I have an interface Model, which is implemented by struct Person.



To get a model instance, I have the following helper functions:



func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}

func newPerson() *Person {
return &Person{}
}


The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).



When I attempted to do something similar for returning a slice of models, I get an error. Code:



func newModels(c string) Model {
switch c {
case "person":
return newPersons()
}
return nil
}

func newPersons() *Person {
var models Person
return &models
}


Go complains with: cannot use newPersons() (type Person) as type Model in return argument



My goal is to return a slice of whatever model type is requested (whether Person, FutureModel, Terminator2000, w/e). What am I missing, and how can I properly implement such a solution?










share|improve this question
















I have an interface Model, which is implemented by struct Person.



To get a model instance, I have the following helper functions:



func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}

func newPerson() *Person {
return &Person{}
}


The above approach allows me to return a properly typed Person instance (can easily add new models later with same approach).



When I attempted to do something similar for returning a slice of models, I get an error. Code:



func newModels(c string) Model {
switch c {
case "person":
return newPersons()
}
return nil
}

func newPersons() *Person {
var models Person
return &models
}


Go complains with: cannot use newPersons() (type Person) as type Model in return argument



My goal is to return a slice of whatever model type is requested (whether Person, FutureModel, Terminator2000, w/e). What am I missing, and how can I properly implement such a solution?







go






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 12 '17 at 15:14









Flimzy

39.1k106597




39.1k106597










asked Oct 21 '12 at 3:26









Jon L.Jon L.

1,28221329




1,28221329








  • 3





    A slice is different from an array in Go. Since you were really talking about slices, I edited your post to reflect this.

    – Stephen Weinberg
    Oct 21 '12 at 4:15











  • Stephen, thanks, appreciated :-)

    – Jon L.
    Oct 21 '12 at 4:23











  • @JonL. Did you ever figure this out? I'm trying to do the same thing so that I don't have to repeat a ton of code for my /api/{collection}. I have it working for everything except for an index function that needs to read into a slice.

    – Derek Perkins
    Jul 25 '14 at 3:44













  • @DerekPerkins, I don't recall what I ended up doing here, and I haven't played w/ Go in awhile. Sorry I can't be of more assistance.

    – Jon L.
    Jul 30 '14 at 13:27











  • Contravariance (or is that covariance?) strikes again!

    – David
    Jul 19 '18 at 1:08














  • 3





    A slice is different from an array in Go. Since you were really talking about slices, I edited your post to reflect this.

    – Stephen Weinberg
    Oct 21 '12 at 4:15











  • Stephen, thanks, appreciated :-)

    – Jon L.
    Oct 21 '12 at 4:23











  • @JonL. Did you ever figure this out? I'm trying to do the same thing so that I don't have to repeat a ton of code for my /api/{collection}. I have it working for everything except for an index function that needs to read into a slice.

    – Derek Perkins
    Jul 25 '14 at 3:44













  • @DerekPerkins, I don't recall what I ended up doing here, and I haven't played w/ Go in awhile. Sorry I can't be of more assistance.

    – Jon L.
    Jul 30 '14 at 13:27











  • Contravariance (or is that covariance?) strikes again!

    – David
    Jul 19 '18 at 1:08








3




3





A slice is different from an array in Go. Since you were really talking about slices, I edited your post to reflect this.

– Stephen Weinberg
Oct 21 '12 at 4:15





A slice is different from an array in Go. Since you were really talking about slices, I edited your post to reflect this.

– Stephen Weinberg
Oct 21 '12 at 4:15













Stephen, thanks, appreciated :-)

– Jon L.
Oct 21 '12 at 4:23





Stephen, thanks, appreciated :-)

– Jon L.
Oct 21 '12 at 4:23













@JonL. Did you ever figure this out? I'm trying to do the same thing so that I don't have to repeat a ton of code for my /api/{collection}. I have it working for everything except for an index function that needs to read into a slice.

– Derek Perkins
Jul 25 '14 at 3:44







@JonL. Did you ever figure this out? I'm trying to do the same thing so that I don't have to repeat a ton of code for my /api/{collection}. I have it working for everything except for an index function that needs to read into a slice.

– Derek Perkins
Jul 25 '14 at 3:44















@DerekPerkins, I don't recall what I ended up doing here, and I haven't played w/ Go in awhile. Sorry I can't be of more assistance.

– Jon L.
Jul 30 '14 at 13:27





@DerekPerkins, I don't recall what I ended up doing here, and I haven't played w/ Go in awhile. Sorry I can't be of more assistance.

– Jon L.
Jul 30 '14 at 13:27













Contravariance (or is that covariance?) strikes again!

– David
Jul 19 '18 at 1:08





Contravariance (or is that covariance?) strikes again!

– David
Jul 19 '18 at 1:08












5 Answers
5






active

oldest

votes


















77














This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643



The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.



A Person and a Model have different memory layouts. This is because the types they are slices of have different memory layouts. A Model is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person is a struct whose size depends on the fields it contains. In order to convert from a Person to a Model, you will need to loop over the array and do a type conversion for each element.



Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.



models := make(Model, len(persons))
for i, v := range persons {
models[i] = Model(v)
}
return models


And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.



*Person        // pointer to slice
*Person // slice of pointers





share|improve this answer


























  • Didn't realize at the time, but my answer doesn't directly address the issue raised. This answer addresses it.

    – dskinner
    Oct 21 '12 at 4:12











  • Very nice answer, especially with the explanation about the number of words of memory for each type

    – I82Much
    Oct 21 '12 at 17:16






  • 3





    github.com/golang/go/wiki/InterfaceSlice

    – Dalibor Filus
    Aug 4 '16 at 14:24











  • Well how do you write something in an abstract, generic way then? Imagine you have 100k results from a database query and you have to iterate over them all and create a copy of each dataset. This means you can't have generic interfaces in Go

    – user2312578
    Apr 26 '17 at 14:58











  • Your answer is correct, but the explanation made me think that if I had an interface A which implements my desired interface B I would be able to use a slice of As as a slice of Bs (after all, the memory structure is identical, since they're both interfaces). I was disappointed to discover I can't :(

    – Noam Nelke
    yesterday





















8














Maybe this is an issue with your return type *Person, where it should actually be *Person so to reference that each index of the slice is a reference to a Person, and where a slice is in itself a reference to an array.



Check out the following example:



package main

import (
"fmt"
)

type Model interface {
Name() string
}

type Person struct {}

func (p *Person) Name() string {
return "Me"
}

func NewPersons() (models *Person) {
return models
}

func main() {
var p Model
p = new(Person)
fmt.Println(p.Name())

arr := NewPersons()
arr = append(arr, new(Person))
fmt.Println(arr[0].Name())
}





share|improve this answer
























  • Thanks for the response. While (as you noted) it doesn't directly address the issue at hand, it's an appreciated example nonetheless :-)

    – Jon L.
    Oct 21 '12 at 4:27



















7














As Stephen already answered the question and you're a beginner I emphasize on giving advises.



A better way of working with go's interfaces is not to have a constructor returning
the interface as you might be used to from other languages, like java, but to have
a constructor for each object independently, as they implement the interface implicitly.



Instead of



newModel(type string) Model { ... }


you should do



newPerson() *Person { ... }
newPolitician() *Politician { ... }


with Person and Politician both implementing the methods of Model.
You can still use Person or Politician everywhere where a Model
is accepted, but you can also implement other interfaces.



With your method you would be limited to Model until you do a manual conversion to
another interface type.



Suppose I have a Person which implements the method Walk() and a Model implements ShowOff(), the following would not work straight forward:



newModel("person").ShowOff()
newModel("person").Walk() // Does not compile, Model has no method Walk


However this would:



newPerson().ShowOff()
newPerson().Walk()





share|improve this answer
























  • You're correct :-( My approach is my attempt to generically provide access to models via a ReST API. So a request to /api/{collection} would dynamically interact w/ the requested collection. Can you suggest an alternative solution without explicitly testing the requested collection across multiple functions? I guess what I'm looking for is a way to specify a generic return type without losing knowledge of it's type.

    – Jon L.
    Oct 21 '12 at 4:45






  • 2





    Knowledge of the type is always preserved, even if you return interface{}, the problem is that you're then need to do runtime type assertions instead of compiler type checking. A generic solution for name -> object without runtime assertions is only possible using generics, which go does not support. So if you do this, you have to live with reflection or the drawbacks of your solution.

    – nemo
    Oct 21 '12 at 14:13











  • point is Model != Person or even Model != Politician. That's the issue.

    – user2312578
    Apr 26 '17 at 15:05











  • @dalu Correct. I mention this at the top of my answer as well: this answer gives complementary information regarding typing and go interface conventions that the OP did not seem to know about but the accepted answer did not address.

    – nemo
    Apr 26 '17 at 17:07



















2














Types T and T are distinct types and distinct are their methods as well, even when satisfying the same interface. IOW, every type satisfying Model must implement all of the Model's methods by itself - the method receiver can be only one specific type.






share|improve this answer































    2














    As others have already answered, T is a distinct type. I'd just like to add that a simple utility can be used to convert them generically.



    import "reflect"

    // Convert a slice or array of a specific type to array of interface{}
    func ToIntf(s interface{}) interface{} {
    v := reflect.ValueOf(s)
    // There is no need to check, we want to panic if it's not slice or array
    intf := make(interface{}, v.Len())
    for i := 0; i < v.Len(); i++ {
    intf[i] = v.Index(i).Interface()
    }
    return intf
    }


    Now, you can use it like this:



    ToIntf(int{1,2,3})





    share|improve this answer























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f12994679%2fgolang-slice-of-struct-slice-of-interface-it-implements%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      77














      This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643



      The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.



      A Person and a Model have different memory layouts. This is because the types they are slices of have different memory layouts. A Model is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person is a struct whose size depends on the fields it contains. In order to convert from a Person to a Model, you will need to loop over the array and do a type conversion for each element.



      Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.



      models := make(Model, len(persons))
      for i, v := range persons {
      models[i] = Model(v)
      }
      return models


      And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.



      *Person        // pointer to slice
      *Person // slice of pointers





      share|improve this answer


























      • Didn't realize at the time, but my answer doesn't directly address the issue raised. This answer addresses it.

        – dskinner
        Oct 21 '12 at 4:12











      • Very nice answer, especially with the explanation about the number of words of memory for each type

        – I82Much
        Oct 21 '12 at 17:16






      • 3





        github.com/golang/go/wiki/InterfaceSlice

        – Dalibor Filus
        Aug 4 '16 at 14:24











      • Well how do you write something in an abstract, generic way then? Imagine you have 100k results from a database query and you have to iterate over them all and create a copy of each dataset. This means you can't have generic interfaces in Go

        – user2312578
        Apr 26 '17 at 14:58











      • Your answer is correct, but the explanation made me think that if I had an interface A which implements my desired interface B I would be able to use a slice of As as a slice of Bs (after all, the memory structure is identical, since they're both interfaces). I was disappointed to discover I can't :(

        – Noam Nelke
        yesterday


















      77














      This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643



      The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.



      A Person and a Model have different memory layouts. This is because the types they are slices of have different memory layouts. A Model is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person is a struct whose size depends on the fields it contains. In order to convert from a Person to a Model, you will need to loop over the array and do a type conversion for each element.



      Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.



      models := make(Model, len(persons))
      for i, v := range persons {
      models[i] = Model(v)
      }
      return models


      And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.



      *Person        // pointer to slice
      *Person // slice of pointers





      share|improve this answer


























      • Didn't realize at the time, but my answer doesn't directly address the issue raised. This answer addresses it.

        – dskinner
        Oct 21 '12 at 4:12











      • Very nice answer, especially with the explanation about the number of words of memory for each type

        – I82Much
        Oct 21 '12 at 17:16






      • 3





        github.com/golang/go/wiki/InterfaceSlice

        – Dalibor Filus
        Aug 4 '16 at 14:24











      • Well how do you write something in an abstract, generic way then? Imagine you have 100k results from a database query and you have to iterate over them all and create a copy of each dataset. This means you can't have generic interfaces in Go

        – user2312578
        Apr 26 '17 at 14:58











      • Your answer is correct, but the explanation made me think that if I had an interface A which implements my desired interface B I would be able to use a slice of As as a slice of Bs (after all, the memory structure is identical, since they're both interfaces). I was disappointed to discover I can't :(

        – Noam Nelke
        yesterday
















      77












      77








      77







      This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643



      The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.



      A Person and a Model have different memory layouts. This is because the types they are slices of have different memory layouts. A Model is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person is a struct whose size depends on the fields it contains. In order to convert from a Person to a Model, you will need to loop over the array and do a type conversion for each element.



      Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.



      models := make(Model, len(persons))
      for i, v := range persons {
      models[i] = Model(v)
      }
      return models


      And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.



      *Person        // pointer to slice
      *Person // slice of pointers





      share|improve this answer















      This is very similar to a question I just answered: https://stackoverflow.com/a/12990540/727643



      The short answer is that you are correct. A slice of structs is not equal to a slice of an interface the struct implements.



      A Person and a Model have different memory layouts. This is because the types they are slices of have different memory layouts. A Model is an interface value which means that in memory it is two words in size. One word for the type information, the other for the data. A Person is a struct whose size depends on the fields it contains. In order to convert from a Person to a Model, you will need to loop over the array and do a type conversion for each element.



      Since this conversion is an O(n) operation and would result in a new slice being created, Go refuses to do it implicitly. You can do it explicitly with the following code.



      models := make(Model, len(persons))
      for i, v := range persons {
      models[i] = Model(v)
      }
      return models


      And as dskinner pointed out, you most likely want a slice of pointers and not a pointer to a slice. A pointer to a slice is not normally needed.



      *Person        // pointer to slice
      *Person // slice of pointers






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited May 23 '17 at 12:18









      Community

      11




      11










      answered Oct 21 '12 at 3:59









      Stephen WeinbergStephen Weinberg

      34.1k99495




      34.1k99495













      • Didn't realize at the time, but my answer doesn't directly address the issue raised. This answer addresses it.

        – dskinner
        Oct 21 '12 at 4:12











      • Very nice answer, especially with the explanation about the number of words of memory for each type

        – I82Much
        Oct 21 '12 at 17:16






      • 3





        github.com/golang/go/wiki/InterfaceSlice

        – Dalibor Filus
        Aug 4 '16 at 14:24











      • Well how do you write something in an abstract, generic way then? Imagine you have 100k results from a database query and you have to iterate over them all and create a copy of each dataset. This means you can't have generic interfaces in Go

        – user2312578
        Apr 26 '17 at 14:58











      • Your answer is correct, but the explanation made me think that if I had an interface A which implements my desired interface B I would be able to use a slice of As as a slice of Bs (after all, the memory structure is identical, since they're both interfaces). I was disappointed to discover I can't :(

        – Noam Nelke
        yesterday





















      • Didn't realize at the time, but my answer doesn't directly address the issue raised. This answer addresses it.

        – dskinner
        Oct 21 '12 at 4:12











      • Very nice answer, especially with the explanation about the number of words of memory for each type

        – I82Much
        Oct 21 '12 at 17:16






      • 3





        github.com/golang/go/wiki/InterfaceSlice

        – Dalibor Filus
        Aug 4 '16 at 14:24











      • Well how do you write something in an abstract, generic way then? Imagine you have 100k results from a database query and you have to iterate over them all and create a copy of each dataset. This means you can't have generic interfaces in Go

        – user2312578
        Apr 26 '17 at 14:58











      • Your answer is correct, but the explanation made me think that if I had an interface A which implements my desired interface B I would be able to use a slice of As as a slice of Bs (after all, the memory structure is identical, since they're both interfaces). I was disappointed to discover I can't :(

        – Noam Nelke
        yesterday



















      Didn't realize at the time, but my answer doesn't directly address the issue raised. This answer addresses it.

      – dskinner
      Oct 21 '12 at 4:12





      Didn't realize at the time, but my answer doesn't directly address the issue raised. This answer addresses it.

      – dskinner
      Oct 21 '12 at 4:12













      Very nice answer, especially with the explanation about the number of words of memory for each type

      – I82Much
      Oct 21 '12 at 17:16





      Very nice answer, especially with the explanation about the number of words of memory for each type

      – I82Much
      Oct 21 '12 at 17:16




      3




      3





      github.com/golang/go/wiki/InterfaceSlice

      – Dalibor Filus
      Aug 4 '16 at 14:24





      github.com/golang/go/wiki/InterfaceSlice

      – Dalibor Filus
      Aug 4 '16 at 14:24













      Well how do you write something in an abstract, generic way then? Imagine you have 100k results from a database query and you have to iterate over them all and create a copy of each dataset. This means you can't have generic interfaces in Go

      – user2312578
      Apr 26 '17 at 14:58





      Well how do you write something in an abstract, generic way then? Imagine you have 100k results from a database query and you have to iterate over them all and create a copy of each dataset. This means you can't have generic interfaces in Go

      – user2312578
      Apr 26 '17 at 14:58













      Your answer is correct, but the explanation made me think that if I had an interface A which implements my desired interface B I would be able to use a slice of As as a slice of Bs (after all, the memory structure is identical, since they're both interfaces). I was disappointed to discover I can't :(

      – Noam Nelke
      yesterday







      Your answer is correct, but the explanation made me think that if I had an interface A which implements my desired interface B I would be able to use a slice of As as a slice of Bs (after all, the memory structure is identical, since they're both interfaces). I was disappointed to discover I can't :(

      – Noam Nelke
      yesterday















      8














      Maybe this is an issue with your return type *Person, where it should actually be *Person so to reference that each index of the slice is a reference to a Person, and where a slice is in itself a reference to an array.



      Check out the following example:



      package main

      import (
      "fmt"
      )

      type Model interface {
      Name() string
      }

      type Person struct {}

      func (p *Person) Name() string {
      return "Me"
      }

      func NewPersons() (models *Person) {
      return models
      }

      func main() {
      var p Model
      p = new(Person)
      fmt.Println(p.Name())

      arr := NewPersons()
      arr = append(arr, new(Person))
      fmt.Println(arr[0].Name())
      }





      share|improve this answer
























      • Thanks for the response. While (as you noted) it doesn't directly address the issue at hand, it's an appreciated example nonetheless :-)

        – Jon L.
        Oct 21 '12 at 4:27
















      8














      Maybe this is an issue with your return type *Person, where it should actually be *Person so to reference that each index of the slice is a reference to a Person, and where a slice is in itself a reference to an array.



      Check out the following example:



      package main

      import (
      "fmt"
      )

      type Model interface {
      Name() string
      }

      type Person struct {}

      func (p *Person) Name() string {
      return "Me"
      }

      func NewPersons() (models *Person) {
      return models
      }

      func main() {
      var p Model
      p = new(Person)
      fmt.Println(p.Name())

      arr := NewPersons()
      arr = append(arr, new(Person))
      fmt.Println(arr[0].Name())
      }





      share|improve this answer
























      • Thanks for the response. While (as you noted) it doesn't directly address the issue at hand, it's an appreciated example nonetheless :-)

        – Jon L.
        Oct 21 '12 at 4:27














      8












      8








      8







      Maybe this is an issue with your return type *Person, where it should actually be *Person so to reference that each index of the slice is a reference to a Person, and where a slice is in itself a reference to an array.



      Check out the following example:



      package main

      import (
      "fmt"
      )

      type Model interface {
      Name() string
      }

      type Person struct {}

      func (p *Person) Name() string {
      return "Me"
      }

      func NewPersons() (models *Person) {
      return models
      }

      func main() {
      var p Model
      p = new(Person)
      fmt.Println(p.Name())

      arr := NewPersons()
      arr = append(arr, new(Person))
      fmt.Println(arr[0].Name())
      }





      share|improve this answer













      Maybe this is an issue with your return type *Person, where it should actually be *Person so to reference that each index of the slice is a reference to a Person, and where a slice is in itself a reference to an array.



      Check out the following example:



      package main

      import (
      "fmt"
      )

      type Model interface {
      Name() string
      }

      type Person struct {}

      func (p *Person) Name() string {
      return "Me"
      }

      func NewPersons() (models *Person) {
      return models
      }

      func main() {
      var p Model
      p = new(Person)
      fmt.Println(p.Name())

      arr := NewPersons()
      arr = append(arr, new(Person))
      fmt.Println(arr[0].Name())
      }






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Oct 21 '12 at 4:05









      dskinnerdskinner

      6,86012541




      6,86012541













      • Thanks for the response. While (as you noted) it doesn't directly address the issue at hand, it's an appreciated example nonetheless :-)

        – Jon L.
        Oct 21 '12 at 4:27



















      • Thanks for the response. While (as you noted) it doesn't directly address the issue at hand, it's an appreciated example nonetheless :-)

        – Jon L.
        Oct 21 '12 at 4:27

















      Thanks for the response. While (as you noted) it doesn't directly address the issue at hand, it's an appreciated example nonetheless :-)

      – Jon L.
      Oct 21 '12 at 4:27





      Thanks for the response. While (as you noted) it doesn't directly address the issue at hand, it's an appreciated example nonetheless :-)

      – Jon L.
      Oct 21 '12 at 4:27











      7














      As Stephen already answered the question and you're a beginner I emphasize on giving advises.



      A better way of working with go's interfaces is not to have a constructor returning
      the interface as you might be used to from other languages, like java, but to have
      a constructor for each object independently, as they implement the interface implicitly.



      Instead of



      newModel(type string) Model { ... }


      you should do



      newPerson() *Person { ... }
      newPolitician() *Politician { ... }


      with Person and Politician both implementing the methods of Model.
      You can still use Person or Politician everywhere where a Model
      is accepted, but you can also implement other interfaces.



      With your method you would be limited to Model until you do a manual conversion to
      another interface type.



      Suppose I have a Person which implements the method Walk() and a Model implements ShowOff(), the following would not work straight forward:



      newModel("person").ShowOff()
      newModel("person").Walk() // Does not compile, Model has no method Walk


      However this would:



      newPerson().ShowOff()
      newPerson().Walk()





      share|improve this answer
























      • You're correct :-( My approach is my attempt to generically provide access to models via a ReST API. So a request to /api/{collection} would dynamically interact w/ the requested collection. Can you suggest an alternative solution without explicitly testing the requested collection across multiple functions? I guess what I'm looking for is a way to specify a generic return type without losing knowledge of it's type.

        – Jon L.
        Oct 21 '12 at 4:45






      • 2





        Knowledge of the type is always preserved, even if you return interface{}, the problem is that you're then need to do runtime type assertions instead of compiler type checking. A generic solution for name -> object without runtime assertions is only possible using generics, which go does not support. So if you do this, you have to live with reflection or the drawbacks of your solution.

        – nemo
        Oct 21 '12 at 14:13











      • point is Model != Person or even Model != Politician. That's the issue.

        – user2312578
        Apr 26 '17 at 15:05











      • @dalu Correct. I mention this at the top of my answer as well: this answer gives complementary information regarding typing and go interface conventions that the OP did not seem to know about but the accepted answer did not address.

        – nemo
        Apr 26 '17 at 17:07
















      7














      As Stephen already answered the question and you're a beginner I emphasize on giving advises.



      A better way of working with go's interfaces is not to have a constructor returning
      the interface as you might be used to from other languages, like java, but to have
      a constructor for each object independently, as they implement the interface implicitly.



      Instead of



      newModel(type string) Model { ... }


      you should do



      newPerson() *Person { ... }
      newPolitician() *Politician { ... }


      with Person and Politician both implementing the methods of Model.
      You can still use Person or Politician everywhere where a Model
      is accepted, but you can also implement other interfaces.



      With your method you would be limited to Model until you do a manual conversion to
      another interface type.



      Suppose I have a Person which implements the method Walk() and a Model implements ShowOff(), the following would not work straight forward:



      newModel("person").ShowOff()
      newModel("person").Walk() // Does not compile, Model has no method Walk


      However this would:



      newPerson().ShowOff()
      newPerson().Walk()





      share|improve this answer
























      • You're correct :-( My approach is my attempt to generically provide access to models via a ReST API. So a request to /api/{collection} would dynamically interact w/ the requested collection. Can you suggest an alternative solution without explicitly testing the requested collection across multiple functions? I guess what I'm looking for is a way to specify a generic return type without losing knowledge of it's type.

        – Jon L.
        Oct 21 '12 at 4:45






      • 2





        Knowledge of the type is always preserved, even if you return interface{}, the problem is that you're then need to do runtime type assertions instead of compiler type checking. A generic solution for name -> object without runtime assertions is only possible using generics, which go does not support. So if you do this, you have to live with reflection or the drawbacks of your solution.

        – nemo
        Oct 21 '12 at 14:13











      • point is Model != Person or even Model != Politician. That's the issue.

        – user2312578
        Apr 26 '17 at 15:05











      • @dalu Correct. I mention this at the top of my answer as well: this answer gives complementary information regarding typing and go interface conventions that the OP did not seem to know about but the accepted answer did not address.

        – nemo
        Apr 26 '17 at 17:07














      7












      7








      7







      As Stephen already answered the question and you're a beginner I emphasize on giving advises.



      A better way of working with go's interfaces is not to have a constructor returning
      the interface as you might be used to from other languages, like java, but to have
      a constructor for each object independently, as they implement the interface implicitly.



      Instead of



      newModel(type string) Model { ... }


      you should do



      newPerson() *Person { ... }
      newPolitician() *Politician { ... }


      with Person and Politician both implementing the methods of Model.
      You can still use Person or Politician everywhere where a Model
      is accepted, but you can also implement other interfaces.



      With your method you would be limited to Model until you do a manual conversion to
      another interface type.



      Suppose I have a Person which implements the method Walk() and a Model implements ShowOff(), the following would not work straight forward:



      newModel("person").ShowOff()
      newModel("person").Walk() // Does not compile, Model has no method Walk


      However this would:



      newPerson().ShowOff()
      newPerson().Walk()





      share|improve this answer













      As Stephen already answered the question and you're a beginner I emphasize on giving advises.



      A better way of working with go's interfaces is not to have a constructor returning
      the interface as you might be used to from other languages, like java, but to have
      a constructor for each object independently, as they implement the interface implicitly.



      Instead of



      newModel(type string) Model { ... }


      you should do



      newPerson() *Person { ... }
      newPolitician() *Politician { ... }


      with Person and Politician both implementing the methods of Model.
      You can still use Person or Politician everywhere where a Model
      is accepted, but you can also implement other interfaces.



      With your method you would be limited to Model until you do a manual conversion to
      another interface type.



      Suppose I have a Person which implements the method Walk() and a Model implements ShowOff(), the following would not work straight forward:



      newModel("person").ShowOff()
      newModel("person").Walk() // Does not compile, Model has no method Walk


      However this would:



      newPerson().ShowOff()
      newPerson().Walk()






      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Oct 21 '12 at 4:12









      nemonemo

      36.2k789101




      36.2k789101













      • You're correct :-( My approach is my attempt to generically provide access to models via a ReST API. So a request to /api/{collection} would dynamically interact w/ the requested collection. Can you suggest an alternative solution without explicitly testing the requested collection across multiple functions? I guess what I'm looking for is a way to specify a generic return type without losing knowledge of it's type.

        – Jon L.
        Oct 21 '12 at 4:45






      • 2





        Knowledge of the type is always preserved, even if you return interface{}, the problem is that you're then need to do runtime type assertions instead of compiler type checking. A generic solution for name -> object without runtime assertions is only possible using generics, which go does not support. So if you do this, you have to live with reflection or the drawbacks of your solution.

        – nemo
        Oct 21 '12 at 14:13











      • point is Model != Person or even Model != Politician. That's the issue.

        – user2312578
        Apr 26 '17 at 15:05











      • @dalu Correct. I mention this at the top of my answer as well: this answer gives complementary information regarding typing and go interface conventions that the OP did not seem to know about but the accepted answer did not address.

        – nemo
        Apr 26 '17 at 17:07



















      • You're correct :-( My approach is my attempt to generically provide access to models via a ReST API. So a request to /api/{collection} would dynamically interact w/ the requested collection. Can you suggest an alternative solution without explicitly testing the requested collection across multiple functions? I guess what I'm looking for is a way to specify a generic return type without losing knowledge of it's type.

        – Jon L.
        Oct 21 '12 at 4:45






      • 2





        Knowledge of the type is always preserved, even if you return interface{}, the problem is that you're then need to do runtime type assertions instead of compiler type checking. A generic solution for name -> object without runtime assertions is only possible using generics, which go does not support. So if you do this, you have to live with reflection or the drawbacks of your solution.

        – nemo
        Oct 21 '12 at 14:13











      • point is Model != Person or even Model != Politician. That's the issue.

        – user2312578
        Apr 26 '17 at 15:05











      • @dalu Correct. I mention this at the top of my answer as well: this answer gives complementary information regarding typing and go interface conventions that the OP did not seem to know about but the accepted answer did not address.

        – nemo
        Apr 26 '17 at 17:07

















      You're correct :-( My approach is my attempt to generically provide access to models via a ReST API. So a request to /api/{collection} would dynamically interact w/ the requested collection. Can you suggest an alternative solution without explicitly testing the requested collection across multiple functions? I guess what I'm looking for is a way to specify a generic return type without losing knowledge of it's type.

      – Jon L.
      Oct 21 '12 at 4:45





      You're correct :-( My approach is my attempt to generically provide access to models via a ReST API. So a request to /api/{collection} would dynamically interact w/ the requested collection. Can you suggest an alternative solution without explicitly testing the requested collection across multiple functions? I guess what I'm looking for is a way to specify a generic return type without losing knowledge of it's type.

      – Jon L.
      Oct 21 '12 at 4:45




      2




      2





      Knowledge of the type is always preserved, even if you return interface{}, the problem is that you're then need to do runtime type assertions instead of compiler type checking. A generic solution for name -> object without runtime assertions is only possible using generics, which go does not support. So if you do this, you have to live with reflection or the drawbacks of your solution.

      – nemo
      Oct 21 '12 at 14:13





      Knowledge of the type is always preserved, even if you return interface{}, the problem is that you're then need to do runtime type assertions instead of compiler type checking. A generic solution for name -> object without runtime assertions is only possible using generics, which go does not support. So if you do this, you have to live with reflection or the drawbacks of your solution.

      – nemo
      Oct 21 '12 at 14:13













      point is Model != Person or even Model != Politician. That's the issue.

      – user2312578
      Apr 26 '17 at 15:05





      point is Model != Person or even Model != Politician. That's the issue.

      – user2312578
      Apr 26 '17 at 15:05













      @dalu Correct. I mention this at the top of my answer as well: this answer gives complementary information regarding typing and go interface conventions that the OP did not seem to know about but the accepted answer did not address.

      – nemo
      Apr 26 '17 at 17:07





      @dalu Correct. I mention this at the top of my answer as well: this answer gives complementary information regarding typing and go interface conventions that the OP did not seem to know about but the accepted answer did not address.

      – nemo
      Apr 26 '17 at 17:07











      2














      Types T and T are distinct types and distinct are their methods as well, even when satisfying the same interface. IOW, every type satisfying Model must implement all of the Model's methods by itself - the method receiver can be only one specific type.






      share|improve this answer




























        2














        Types T and T are distinct types and distinct are their methods as well, even when satisfying the same interface. IOW, every type satisfying Model must implement all of the Model's methods by itself - the method receiver can be only one specific type.






        share|improve this answer


























          2












          2








          2







          Types T and T are distinct types and distinct are their methods as well, even when satisfying the same interface. IOW, every type satisfying Model must implement all of the Model's methods by itself - the method receiver can be only one specific type.






          share|improve this answer













          Types T and T are distinct types and distinct are their methods as well, even when satisfying the same interface. IOW, every type satisfying Model must implement all of the Model's methods by itself - the method receiver can be only one specific type.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 21 '12 at 3:58









          zzzzzzzz

          54.5k12131114




          54.5k12131114























              2














              As others have already answered, T is a distinct type. I'd just like to add that a simple utility can be used to convert them generically.



              import "reflect"

              // Convert a slice or array of a specific type to array of interface{}
              func ToIntf(s interface{}) interface{} {
              v := reflect.ValueOf(s)
              // There is no need to check, we want to panic if it's not slice or array
              intf := make(interface{}, v.Len())
              for i := 0; i < v.Len(); i++ {
              intf[i] = v.Index(i).Interface()
              }
              return intf
              }


              Now, you can use it like this:



              ToIntf(int{1,2,3})





              share|improve this answer




























                2














                As others have already answered, T is a distinct type. I'd just like to add that a simple utility can be used to convert them generically.



                import "reflect"

                // Convert a slice or array of a specific type to array of interface{}
                func ToIntf(s interface{}) interface{} {
                v := reflect.ValueOf(s)
                // There is no need to check, we want to panic if it's not slice or array
                intf := make(interface{}, v.Len())
                for i := 0; i < v.Len(); i++ {
                intf[i] = v.Index(i).Interface()
                }
                return intf
                }


                Now, you can use it like this:



                ToIntf(int{1,2,3})





                share|improve this answer


























                  2












                  2








                  2







                  As others have already answered, T is a distinct type. I'd just like to add that a simple utility can be used to convert them generically.



                  import "reflect"

                  // Convert a slice or array of a specific type to array of interface{}
                  func ToIntf(s interface{}) interface{} {
                  v := reflect.ValueOf(s)
                  // There is no need to check, we want to panic if it's not slice or array
                  intf := make(interface{}, v.Len())
                  for i := 0; i < v.Len(); i++ {
                  intf[i] = v.Index(i).Interface()
                  }
                  return intf
                  }


                  Now, you can use it like this:



                  ToIntf(int{1,2,3})





                  share|improve this answer













                  As others have already answered, T is a distinct type. I'd just like to add that a simple utility can be used to convert them generically.



                  import "reflect"

                  // Convert a slice or array of a specific type to array of interface{}
                  func ToIntf(s interface{}) interface{} {
                  v := reflect.ValueOf(s)
                  // There is no need to check, we want to panic if it's not slice or array
                  intf := make(interface{}, v.Len())
                  for i := 0; i < v.Len(); i++ {
                  intf[i] = v.Index(i).Interface()
                  }
                  return intf
                  }


                  Now, you can use it like this:



                  ToIntf(int{1,2,3})






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 28 '15 at 5:00









                  slavikmslavikm

                  483




                  483






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f12994679%2fgolang-slice-of-struct-slice-of-interface-it-implements%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Guess what letter conforming each word

                      Port of Spain

                      Run scheduled task as local user group (not BUILTIN)