Populating an array of structs passed to a function as a pointer










0














I'm want to do data pagination with Google Cloud Platform Datastore and I've found an example on GCP's page (https://cloud.google.com/datastore/docs/concepts/queries) for doing it with Cursors and it works absolutely fine.



The example provided by Google has hardcoded the variables var tasks Task and var task Task and I would like to create a reusable function where I can pass the pointer to a struct array via a parameter typed interface and get this struct populated by this function. For example:



 type MyStruct1 struct 
F1 string


type MyStruct2 struct
F1 int


func list(ctx context.Context, cursorStr string, data interface)
...


func main()
mystruct1 := make(MyStruct1, 0)
list(ctx, "", &mystruct1)

mystruct2 := make(MyStruct2, 0)
list(ctx, "", &mystruct2)



My problem starts when I need to create in this function, a variable to store the record and then append it to the struct array passed as a pointer.



Example from Google



func SnippetIterator_Cursor() 
ctx := context.Background()
client, _ := datastore.NewClient(ctx, "my-proj")
cursorStr := ""
// [START datastore_cursor_paging]
const pageSize = 5
query := datastore.NewQuery("Tasks").Limit(pageSize)
if cursorStr != ""
cursor, err := datastore.DecodeCursor(cursorStr)
if err != nil
log.Fatalf("Bad cursor %q: %v", cursorStr, err)

query = query.Start(cursor)


// Read the tasks.
var tasks Task << THIS IS WHAT I WANT TO BE GENERIC
var task Task. << THIS IS WHAT I WANT TO BE GENERIC
it := client.Run(ctx, query)
_, err := it.Next(&task)
for err == nil
tasks = append(tasks, task)
_, err = it.Next(&task)

if err != iterator.Done
log.Fatalf("Failed fetching results: %v", err)


// Get the cursor for the next page of results.
nextCursor, err := it.Cursor()
// [END datastore_cursor_paging]
_ = err // Check the error.
_ = nextCursor // Use nextCursor.String as the next page's token.



My Generic function based on the code above



func list(ctx context.Context, kind string, data interface, pageSize int, cursorStr string) string 
query := datastore.NewQuery(kind).Limit(pageSize)
if cursorStr != ""
cursor, err := datastore.DecodeCursor(cursorStr)
if err != nil
log.Fatalf("Bad cursor %q: %v", cursorStr, err)

query = query.Start(cursor)

it := query.Run(ctx)

// HERE IS WHERE THE PROBLEM STARTS
var vet interface
var rec interface

k, err := it.Next(rec)
if err != nil
log.Println(err.Error())

for err == nil
log.Println(k, rec) // PROBLEM: The key comes ok but rec comes nil
vet = append(vet, rec)
k, err = it.Next(rec)

log.Println(vet) // PROBLEM: vet has only nils

nextCursor, err := it.Cursor()
if err != nil
log.Println(err.Error())


data = vet
return nextCursor.String()


func TestListFunc()
data := make(Tasks, 0)
cursor := list(ctx, "Tasks", &data, 10, "")
x, _ := json.MarshalIndent(data, " ", " ")
log.Println(string(x))



PROBLEM: The Datastore iterator .Next() doesn't seem to store the record in a variable typed interface










share|improve this question


























    0














    I'm want to do data pagination with Google Cloud Platform Datastore and I've found an example on GCP's page (https://cloud.google.com/datastore/docs/concepts/queries) for doing it with Cursors and it works absolutely fine.



    The example provided by Google has hardcoded the variables var tasks Task and var task Task and I would like to create a reusable function where I can pass the pointer to a struct array via a parameter typed interface and get this struct populated by this function. For example:



     type MyStruct1 struct 
    F1 string


    type MyStruct2 struct
    F1 int


    func list(ctx context.Context, cursorStr string, data interface)
    ...


    func main()
    mystruct1 := make(MyStruct1, 0)
    list(ctx, "", &mystruct1)

    mystruct2 := make(MyStruct2, 0)
    list(ctx, "", &mystruct2)



    My problem starts when I need to create in this function, a variable to store the record and then append it to the struct array passed as a pointer.



    Example from Google



    func SnippetIterator_Cursor() 
    ctx := context.Background()
    client, _ := datastore.NewClient(ctx, "my-proj")
    cursorStr := ""
    // [START datastore_cursor_paging]
    const pageSize = 5
    query := datastore.NewQuery("Tasks").Limit(pageSize)
    if cursorStr != ""
    cursor, err := datastore.DecodeCursor(cursorStr)
    if err != nil
    log.Fatalf("Bad cursor %q: %v", cursorStr, err)

    query = query.Start(cursor)


    // Read the tasks.
    var tasks Task << THIS IS WHAT I WANT TO BE GENERIC
    var task Task. << THIS IS WHAT I WANT TO BE GENERIC
    it := client.Run(ctx, query)
    _, err := it.Next(&task)
    for err == nil
    tasks = append(tasks, task)
    _, err = it.Next(&task)

    if err != iterator.Done
    log.Fatalf("Failed fetching results: %v", err)


    // Get the cursor for the next page of results.
    nextCursor, err := it.Cursor()
    // [END datastore_cursor_paging]
    _ = err // Check the error.
    _ = nextCursor // Use nextCursor.String as the next page's token.



    My Generic function based on the code above



    func list(ctx context.Context, kind string, data interface, pageSize int, cursorStr string) string 
    query := datastore.NewQuery(kind).Limit(pageSize)
    if cursorStr != ""
    cursor, err := datastore.DecodeCursor(cursorStr)
    if err != nil
    log.Fatalf("Bad cursor %q: %v", cursorStr, err)

    query = query.Start(cursor)

    it := query.Run(ctx)

    // HERE IS WHERE THE PROBLEM STARTS
    var vet interface
    var rec interface

    k, err := it.Next(rec)
    if err != nil
    log.Println(err.Error())

    for err == nil
    log.Println(k, rec) // PROBLEM: The key comes ok but rec comes nil
    vet = append(vet, rec)
    k, err = it.Next(rec)

    log.Println(vet) // PROBLEM: vet has only nils

    nextCursor, err := it.Cursor()
    if err != nil
    log.Println(err.Error())


    data = vet
    return nextCursor.String()


    func TestListFunc()
    data := make(Tasks, 0)
    cursor := list(ctx, "Tasks", &data, 10, "")
    x, _ := json.MarshalIndent(data, " ", " ")
    log.Println(string(x))



    PROBLEM: The Datastore iterator .Next() doesn't seem to store the record in a variable typed interface










    share|improve this question
























      0












      0








      0







      I'm want to do data pagination with Google Cloud Platform Datastore and I've found an example on GCP's page (https://cloud.google.com/datastore/docs/concepts/queries) for doing it with Cursors and it works absolutely fine.



      The example provided by Google has hardcoded the variables var tasks Task and var task Task and I would like to create a reusable function where I can pass the pointer to a struct array via a parameter typed interface and get this struct populated by this function. For example:



       type MyStruct1 struct 
      F1 string


      type MyStruct2 struct
      F1 int


      func list(ctx context.Context, cursorStr string, data interface)
      ...


      func main()
      mystruct1 := make(MyStruct1, 0)
      list(ctx, "", &mystruct1)

      mystruct2 := make(MyStruct2, 0)
      list(ctx, "", &mystruct2)



      My problem starts when I need to create in this function, a variable to store the record and then append it to the struct array passed as a pointer.



      Example from Google



      func SnippetIterator_Cursor() 
      ctx := context.Background()
      client, _ := datastore.NewClient(ctx, "my-proj")
      cursorStr := ""
      // [START datastore_cursor_paging]
      const pageSize = 5
      query := datastore.NewQuery("Tasks").Limit(pageSize)
      if cursorStr != ""
      cursor, err := datastore.DecodeCursor(cursorStr)
      if err != nil
      log.Fatalf("Bad cursor %q: %v", cursorStr, err)

      query = query.Start(cursor)


      // Read the tasks.
      var tasks Task << THIS IS WHAT I WANT TO BE GENERIC
      var task Task. << THIS IS WHAT I WANT TO BE GENERIC
      it := client.Run(ctx, query)
      _, err := it.Next(&task)
      for err == nil
      tasks = append(tasks, task)
      _, err = it.Next(&task)

      if err != iterator.Done
      log.Fatalf("Failed fetching results: %v", err)


      // Get the cursor for the next page of results.
      nextCursor, err := it.Cursor()
      // [END datastore_cursor_paging]
      _ = err // Check the error.
      _ = nextCursor // Use nextCursor.String as the next page's token.



      My Generic function based on the code above



      func list(ctx context.Context, kind string, data interface, pageSize int, cursorStr string) string 
      query := datastore.NewQuery(kind).Limit(pageSize)
      if cursorStr != ""
      cursor, err := datastore.DecodeCursor(cursorStr)
      if err != nil
      log.Fatalf("Bad cursor %q: %v", cursorStr, err)

      query = query.Start(cursor)

      it := query.Run(ctx)

      // HERE IS WHERE THE PROBLEM STARTS
      var vet interface
      var rec interface

      k, err := it.Next(rec)
      if err != nil
      log.Println(err.Error())

      for err == nil
      log.Println(k, rec) // PROBLEM: The key comes ok but rec comes nil
      vet = append(vet, rec)
      k, err = it.Next(rec)

      log.Println(vet) // PROBLEM: vet has only nils

      nextCursor, err := it.Cursor()
      if err != nil
      log.Println(err.Error())


      data = vet
      return nextCursor.String()


      func TestListFunc()
      data := make(Tasks, 0)
      cursor := list(ctx, "Tasks", &data, 10, "")
      x, _ := json.MarshalIndent(data, " ", " ")
      log.Println(string(x))



      PROBLEM: The Datastore iterator .Next() doesn't seem to store the record in a variable typed interface










      share|improve this question













      I'm want to do data pagination with Google Cloud Platform Datastore and I've found an example on GCP's page (https://cloud.google.com/datastore/docs/concepts/queries) for doing it with Cursors and it works absolutely fine.



      The example provided by Google has hardcoded the variables var tasks Task and var task Task and I would like to create a reusable function where I can pass the pointer to a struct array via a parameter typed interface and get this struct populated by this function. For example:



       type MyStruct1 struct 
      F1 string


      type MyStruct2 struct
      F1 int


      func list(ctx context.Context, cursorStr string, data interface)
      ...


      func main()
      mystruct1 := make(MyStruct1, 0)
      list(ctx, "", &mystruct1)

      mystruct2 := make(MyStruct2, 0)
      list(ctx, "", &mystruct2)



      My problem starts when I need to create in this function, a variable to store the record and then append it to the struct array passed as a pointer.



      Example from Google



      func SnippetIterator_Cursor() 
      ctx := context.Background()
      client, _ := datastore.NewClient(ctx, "my-proj")
      cursorStr := ""
      // [START datastore_cursor_paging]
      const pageSize = 5
      query := datastore.NewQuery("Tasks").Limit(pageSize)
      if cursorStr != ""
      cursor, err := datastore.DecodeCursor(cursorStr)
      if err != nil
      log.Fatalf("Bad cursor %q: %v", cursorStr, err)

      query = query.Start(cursor)


      // Read the tasks.
      var tasks Task << THIS IS WHAT I WANT TO BE GENERIC
      var task Task. << THIS IS WHAT I WANT TO BE GENERIC
      it := client.Run(ctx, query)
      _, err := it.Next(&task)
      for err == nil
      tasks = append(tasks, task)
      _, err = it.Next(&task)

      if err != iterator.Done
      log.Fatalf("Failed fetching results: %v", err)


      // Get the cursor for the next page of results.
      nextCursor, err := it.Cursor()
      // [END datastore_cursor_paging]
      _ = err // Check the error.
      _ = nextCursor // Use nextCursor.String as the next page's token.



      My Generic function based on the code above



      func list(ctx context.Context, kind string, data interface, pageSize int, cursorStr string) string 
      query := datastore.NewQuery(kind).Limit(pageSize)
      if cursorStr != ""
      cursor, err := datastore.DecodeCursor(cursorStr)
      if err != nil
      log.Fatalf("Bad cursor %q: %v", cursorStr, err)

      query = query.Start(cursor)

      it := query.Run(ctx)

      // HERE IS WHERE THE PROBLEM STARTS
      var vet interface
      var rec interface

      k, err := it.Next(rec)
      if err != nil
      log.Println(err.Error())

      for err == nil
      log.Println(k, rec) // PROBLEM: The key comes ok but rec comes nil
      vet = append(vet, rec)
      k, err = it.Next(rec)

      log.Println(vet) // PROBLEM: vet has only nils

      nextCursor, err := it.Cursor()
      if err != nil
      log.Println(err.Error())


      data = vet
      return nextCursor.String()


      func TestListFunc()
      data := make(Tasks, 0)
      cursor := list(ctx, "Tasks", &data, 10, "")
      x, _ := json.MarshalIndent(data, " ", " ")
      log.Println(string(x))



      PROBLEM: The Datastore iterator .Next() doesn't seem to store the record in a variable typed interface







      go google-cloud-platform google-cloud-datastore






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 12 '18 at 0:48









      TTKDroid

      1538




      1538






















          1 Answer
          1






          active

          oldest

          votes


















          1














          Use the reflect package:



          func list(ctx context.Context, kind string, dst interface, pageSize int, cursorStr string) string 
          client, _ := datastore.NewClient(ctx, "my-proj")
          query := datastore.NewQuery(kind).Limit(pageSize)
          if cursorStr != ""
          cursor, err := datastore.DecodeCursor(cursorStr)
          if err != nil
          log.Fatalf("Bad cursor %q: %v", cursorStr, err)

          query = query.Start(cursor)


          // Get reflect value for the result slice.
          results := reflect.ValueOf(dst).Elem()

          // Allocate new value of the slice element type.
          // resultp is pointer to that value.
          resultp := reflect.New(results.Type().Elem())

          it := client.Run(ctx, query)
          _, err := it.Next(resultp.Interface())
          for err == nil
          // Append last value to results
          results.Set(reflect.Append(results, resultp.Elem())

          _, err = it.Next(resultp.Interface())

          if err != iterator.Done
          log.Fatalf("Failed fetching results: %v", err)


          // Get the cursor for the next page of results.
          nextCursor, err := it.Cursor()
          // [END datastore_cursor_paging]
          _ = err // Check the error.
          _ = nextCursor // Use nextCursor.String as the next page's token.



          Call the function with a pointer to the destination slice:



          var data Tasks
          cursor := list(ctx, "Tasks", &data, 10, "")





          share|improve this answer






















          • It works @ThunderCat! You're the GURU of reflection mate! Well done! Thank you very much!
            – TTKDroid
            Nov 12 '18 at 4:30










          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%2f53254726%2fpopulating-an-array-of-structs-passed-to-a-function-as-a-pointer%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Use the reflect package:



          func list(ctx context.Context, kind string, dst interface, pageSize int, cursorStr string) string 
          client, _ := datastore.NewClient(ctx, "my-proj")
          query := datastore.NewQuery(kind).Limit(pageSize)
          if cursorStr != ""
          cursor, err := datastore.DecodeCursor(cursorStr)
          if err != nil
          log.Fatalf("Bad cursor %q: %v", cursorStr, err)

          query = query.Start(cursor)


          // Get reflect value for the result slice.
          results := reflect.ValueOf(dst).Elem()

          // Allocate new value of the slice element type.
          // resultp is pointer to that value.
          resultp := reflect.New(results.Type().Elem())

          it := client.Run(ctx, query)
          _, err := it.Next(resultp.Interface())
          for err == nil
          // Append last value to results
          results.Set(reflect.Append(results, resultp.Elem())

          _, err = it.Next(resultp.Interface())

          if err != iterator.Done
          log.Fatalf("Failed fetching results: %v", err)


          // Get the cursor for the next page of results.
          nextCursor, err := it.Cursor()
          // [END datastore_cursor_paging]
          _ = err // Check the error.
          _ = nextCursor // Use nextCursor.String as the next page's token.



          Call the function with a pointer to the destination slice:



          var data Tasks
          cursor := list(ctx, "Tasks", &data, 10, "")





          share|improve this answer






















          • It works @ThunderCat! You're the GURU of reflection mate! Well done! Thank you very much!
            – TTKDroid
            Nov 12 '18 at 4:30















          1














          Use the reflect package:



          func list(ctx context.Context, kind string, dst interface, pageSize int, cursorStr string) string 
          client, _ := datastore.NewClient(ctx, "my-proj")
          query := datastore.NewQuery(kind).Limit(pageSize)
          if cursorStr != ""
          cursor, err := datastore.DecodeCursor(cursorStr)
          if err != nil
          log.Fatalf("Bad cursor %q: %v", cursorStr, err)

          query = query.Start(cursor)


          // Get reflect value for the result slice.
          results := reflect.ValueOf(dst).Elem()

          // Allocate new value of the slice element type.
          // resultp is pointer to that value.
          resultp := reflect.New(results.Type().Elem())

          it := client.Run(ctx, query)
          _, err := it.Next(resultp.Interface())
          for err == nil
          // Append last value to results
          results.Set(reflect.Append(results, resultp.Elem())

          _, err = it.Next(resultp.Interface())

          if err != iterator.Done
          log.Fatalf("Failed fetching results: %v", err)


          // Get the cursor for the next page of results.
          nextCursor, err := it.Cursor()
          // [END datastore_cursor_paging]
          _ = err // Check the error.
          _ = nextCursor // Use nextCursor.String as the next page's token.



          Call the function with a pointer to the destination slice:



          var data Tasks
          cursor := list(ctx, "Tasks", &data, 10, "")





          share|improve this answer






















          • It works @ThunderCat! You're the GURU of reflection mate! Well done! Thank you very much!
            – TTKDroid
            Nov 12 '18 at 4:30













          1












          1








          1






          Use the reflect package:



          func list(ctx context.Context, kind string, dst interface, pageSize int, cursorStr string) string 
          client, _ := datastore.NewClient(ctx, "my-proj")
          query := datastore.NewQuery(kind).Limit(pageSize)
          if cursorStr != ""
          cursor, err := datastore.DecodeCursor(cursorStr)
          if err != nil
          log.Fatalf("Bad cursor %q: %v", cursorStr, err)

          query = query.Start(cursor)


          // Get reflect value for the result slice.
          results := reflect.ValueOf(dst).Elem()

          // Allocate new value of the slice element type.
          // resultp is pointer to that value.
          resultp := reflect.New(results.Type().Elem())

          it := client.Run(ctx, query)
          _, err := it.Next(resultp.Interface())
          for err == nil
          // Append last value to results
          results.Set(reflect.Append(results, resultp.Elem())

          _, err = it.Next(resultp.Interface())

          if err != iterator.Done
          log.Fatalf("Failed fetching results: %v", err)


          // Get the cursor for the next page of results.
          nextCursor, err := it.Cursor()
          // [END datastore_cursor_paging]
          _ = err // Check the error.
          _ = nextCursor // Use nextCursor.String as the next page's token.



          Call the function with a pointer to the destination slice:



          var data Tasks
          cursor := list(ctx, "Tasks", &data, 10, "")





          share|improve this answer














          Use the reflect package:



          func list(ctx context.Context, kind string, dst interface, pageSize int, cursorStr string) string 
          client, _ := datastore.NewClient(ctx, "my-proj")
          query := datastore.NewQuery(kind).Limit(pageSize)
          if cursorStr != ""
          cursor, err := datastore.DecodeCursor(cursorStr)
          if err != nil
          log.Fatalf("Bad cursor %q: %v", cursorStr, err)

          query = query.Start(cursor)


          // Get reflect value for the result slice.
          results := reflect.ValueOf(dst).Elem()

          // Allocate new value of the slice element type.
          // resultp is pointer to that value.
          resultp := reflect.New(results.Type().Elem())

          it := client.Run(ctx, query)
          _, err := it.Next(resultp.Interface())
          for err == nil
          // Append last value to results
          results.Set(reflect.Append(results, resultp.Elem())

          _, err = it.Next(resultp.Interface())

          if err != iterator.Done
          log.Fatalf("Failed fetching results: %v", err)


          // Get the cursor for the next page of results.
          nextCursor, err := it.Cursor()
          // [END datastore_cursor_paging]
          _ = err // Check the error.
          _ = nextCursor // Use nextCursor.String as the next page's token.



          Call the function with a pointer to the destination slice:



          var data Tasks
          cursor := list(ctx, "Tasks", &data, 10, "")






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 12 '18 at 1:16

























          answered Nov 12 '18 at 1:10









          ThunderCat

          49.7k46280




          49.7k46280











          • It works @ThunderCat! You're the GURU of reflection mate! Well done! Thank you very much!
            – TTKDroid
            Nov 12 '18 at 4:30
















          • It works @ThunderCat! You're the GURU of reflection mate! Well done! Thank you very much!
            – TTKDroid
            Nov 12 '18 at 4:30















          It works @ThunderCat! You're the GURU of reflection mate! Well done! Thank you very much!
          – TTKDroid
          Nov 12 '18 at 4:30




          It works @ThunderCat! You're the GURU of reflection mate! Well done! Thank you very much!
          – TTKDroid
          Nov 12 '18 at 4:30

















          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.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • 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%2f53254726%2fpopulating-an-array-of-structs-passed-to-a-function-as-a-pointer%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

          Kleinkühnau

          Makov (Slowakei)

          Deutsches Schauspielhaus