Pulling off elements in a slice of structs

Hello,

I have a slice of structs I’m passing back from a function. I would have expected to be able to access them in the following manor:

Incomplete code

	myResults, err := model.PullTasks()
	if err == nil {
		for _, Result := range myResults {
			fmt.Println(Result[i].field)
		}
	}

in PHP you would just iterate through the array and your properties would be available to you. I’ve looked up a few things but nothing really showed me the answer.

This is the code I’m using

		for index, Result := range myResults {
			fmt.Print(index)
			fmt.Print(": ")
			fmt.Println(Result)
		}

it does print each index and then the line

Thank you!

Can you please update your example to include a runnable piece of code. Then add what you expected to see when you ran it, and what you saw instead.

Here’s the code

package model

import (
	"fmt"
)

//RequestResults Exported
type RequestResult struct {
	id          int
	assignedto  string
	requester   string
	requestname string
	company     string
	priority    string
	status      string
}

//PullTasks will print out all the records in the database
func PullTasks() ([]RequestResult, error) {
	fmt.Println("Start pull tasks")

	rows, err := db.Query(`
		SELECT
			id,
			assignedto,
			requester,
			requestname,
			company,
			priority,
			status
		FROM
			golang.tasks
		WHERE
			owner = $1 AND active = $2`,
		"Steven Aiello", "y")
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	i := 0

	var results []RequestResult
	for rows.Next() {
		var result RequestResult
		err = rows.Scan(
			&result.id,
			&result.assignedto,
			&result.requester,
			&result.requestname,
			&result.company,
			&result.priority,
			&result.status)
		if err != nil {
			return nil, err
		}

		//fmt.Println(i, result.id, result.assignedto, result.requester,
		//	result.requestname, result.company, result.priority, result.status)

		i++

		results = append(results, result)
	}

	return results, nil
}

Then I’m calling it with

package controller

import (
	"fmt"
	"html/template"
	"net/http"

	"github.com/nasquam/taskmaster/model"
	"github.com/nasquam/taskmaster/viewmodel"
)

type taskmaster struct {
	taskmasterTemplate *template.Template
}

func (h taskmaster) resisterRoutes() {
	http.HandleFunc("/taskmaster", h.tasktHolder)
	http.HandleFunc("/taskmaster/", h.tasktHolder)
}

func (h taskmaster) tasktHolder(w http.ResponseWriter, r *http.Request) {
	model.CookieCheck(w, r)

	myResults, err := model.PullTasks()

	if err == nil {
		for index, Result := range myResults {
			fmt.Print(index)
			fmt.Print(": ")
			fmt.Println(Result)
		}
	}

	viewModel := viewmodel.RequestHolder()
	h.taskmasterTemplate.Execute(w, viewModel)
}

Thanks!

If the error returned from PullTasks is non-nil your code will simply render a blank template. You should check and act on that error, to begin with.

Correct: I understand that, in this example I’m just trying to pull elements off of my slices. This is just some test code I was trying.

If you get an error, nothing will be printed and nothing will be rendered. Which I think is what you say is happening. But it’s not 100% clear.

No it prints to the console. I’m literally just trying to print a single item, not the entire list:

for example:

struct[i].structproperty

That syntax is correct for getting an attribute of a struct in a slice. I don’t think I understand what your issue is. Perhaps, as Dave suggested, being super clear on what you see and what you expect to see instead would help. Preferably with a runnable example.

You cannot index a struct.

When we have the following code:

type result struct{
	bar string
}

func foo() []result [
	return []result{
		result{"bar"},
		result{"barbaraz"},
	}
}

func bar() {
	for _, r := range foo() {
		fmt.Println(r.bar)
	}
}

It will probably work as you expect it.

So not indexing a struct makes complete sense. In my case I have a slice OF TYPE structs (RequestResult):

type RequestResult struct {
	id          int
	assignedto  string
	requester   string
	requestname string
	company     string
	priority    string
	status      string
}

then later in my code (it’s all in my second post here) I create a slice of structs

var results []RequestResult

then I pass the []RequestResult

back to my calling function

when I print it to the screen I see the data: (nothing sensitive here)

0: {1 Aiello Callaghan Need to review Poland configs with Kevin, I don't like the hybrid config. Medium Complete}                              
1: {2 Aiello Callaghan COMPETITIVE WITH HP - (36 sites deployed by Oct 2017 in the U.S.) High Complete}                                        
2: {3 Waiting on Client Callaghan Rework VNX 5800 upgrades (2Tb file upgrade and SAS cards) Critical Complete}                                        
3: {4 Waiting on Client Merchant  Follow up with Merchi if haven't seen email by 6/27 Insurance Medium Complete}                                            
4: {5 Merchant   Merchant  Follow up if haven't heard back by 6/30 STARS Medium Complete}                                                                    
5: {6 Aiello Merchant  Follow up - Carbon Black Discussion Medium Complete}                                                      
6: {7 Aiello Edwards Follow up  - Briefing, ISO 27001, PCI, Gov & Security on "cloud" Medium Complete}                       
7: {8 Aiello Kilcrease Follow up if haven't heard back - briefing SNOW SecOps & GRC Medium Complete}  

So I know my data is coming back.

What I’m trying to do is print the INDIVIDUAL elements in the struct, not the whole struct.

example: in my for loop this prints the whole struct

		for index, Result := range myResults {
			fmt.Print(index)
			fmt.Print(": ")
			fmt.Println(Result)
		}

I want to be able to do this:

		for index, Result := range myResults {
			fmt.Print(index)
			fmt.Print(": ")
			fmt.Println(Result.assignedto)
			fmt.Println(Result.requester   )
		}

Does that clarify?

And exactly this is the way to go…

for index, Result := range myResults {
	fmt.Print(index)
	fmt.Print(": ")
	fmt.Println(Result.assignedto)
	fmt.Println(Result.requester   )
}

But of course, you need to either expose the fields, or move everything into the same package. I’ve just seen it that you are crossing package boundaries in one of your examples…

2 Likes

AAAAAAAAH, THANK YOU SO MUCH!

SON OF A B! The fields in my struct weren’t capitalized. I thought I exported my struct because the Struct name was capitalized.

Thank you so much, learning…

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.