I am new to Go and want to create and initialise an struct array in go. My code is like this
type node struct {
name string
children map[string]int
}
cities:= []node{node{}}
for i := 0; i<47 ;i++ {
cities[i].name=strconv.Itoa(i)
cities[i].children=make(map[string]int)
}
I get the following error:
panic: runtime error: index out of range
goroutine 1 [running]:
panic(0xa6800, 0xc42000a080)
Please help. TIA :)
You are initializing cities as a slice of nodes with one element (an empty node).
You can initialize it to a fixed size with cities := make([]node,47), or you could initialize it to an empty slice, and append to it:
cities := []node{}
for i := 0; i<47 ;i++ {
n := node{name: strconv.Itoa(i), children: map[string]int{}}
cities = append(cities,n)
}
I'd definitely recommend reading this article if you are a bit shaky on how slices work.
This worked for me
type node struct {
name string
children map[string]int
}
cities:=[]*node{}
city:=new(node)
city.name=strconv.Itoa(0)
city.children=make(map[string]int)
cities=append(cities,city)
for i := 1; i<47 ;i++ {
city=new(node)
city.name=strconv.Itoa(i)
city.children=make(map[string]int)
cities=append(cities,city)
}
Related
we have struct and getting null after append struct in golang.
Find below struct with my some part of code in golang.
type XmloutRoomRate struct {
CancellationPolicy Policies `bson:"cancellationPolicy" json:"cancellationPolicy"`
}
type Policies struct {
Policies []RoomPolicies `bson:"policies" json:"policies"`
}
type RoomPolicies struct {
Amount float64 `bson:"amount" json:"amount"`
DaysBeforeCheckIn int `bson:"daysBeforeCheckIn" json:"daysBeforeCheckIn"`
}
cancelPolicyMain := Policies{}
cancelPolicy := RoomPolicies{}
if cancelAmount < 0 {
cancelPolicy.Amount = cancelAmount
cancelPolicy.DaysBeforeCheckIn = cancelDay
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
}else{
cancelPolicyMain = agodaPolicies{}
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
}
when data present getting proper data structure.
"cancellationPolicy": {
"policies": [
{
"amount": 5141.58,
"daysBeforeCheckIn": 5
}
]
}
But when data not available getting struct with null value.
"cancellationPolicy": {
"policies": null
}
We need my actual output with blank array [].
"cancellationPolicy": {
"policies": []
}
nil slice values are marshaled into JSON null values. This is documented at json.Marshal():
Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.
Non-nil empty slices are marshaled into empty JSON arrays. So simply initialize Policies.Policies to a non-nil empty slice, and it will be [] in the output:
cancelPolicyMain = Policies{Policies: []RoomPolicies{}}
Test code:
const cancelDay = 1
for cancelAmount := -500.0; cancelAmount <= 501; cancelAmount += 1000 {
cancelPolicyMain := Policies{}
cancelPolicy := RoomPolicies{}
if cancelAmount < 0 {
cancelPolicy.Amount = cancelAmount
cancelPolicy.DaysBeforeCheckIn = cancelDay
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies, cancelPolicy)
} else {
cancelPolicyMain = Policies{Policies: []RoomPolicies{}}
cancelPolicyMain.Policies = append(cancelPolicyMain.Policies)
}
x := XmloutRoomRate{cancelPolicyMain}
if err := json.NewEncoder(os.Stdout).Encode(x); err != nil {
panic(err)
}
}
Output (try it on the Go Playground):
{"cancellationPolicy":{"policies":[{"amount":-500,"daysBeforeCheckIn":1}]}}
{"cancellationPolicy":{"policies":[]}}
In an array, the meaning of a "null" entry is clear: It means this array entry is missing.
In an object aka dictionary, there are different ways to indicate "no entry": The key might not be there. Or the key might not be there, but with an empty array as value. Or the key might be there, but with a "null" value.
You really need agreement between the provider of the data and the client processing it, what each of these mean. And since it's often hard to change what the data provider does, translate what you get into what you need.
So you have to decide what it means if "policies" does not exist as a key, or if it exists as a null value. I've seen software that wouldn't produce arrays with one element, but would provide the single element instead. So "policies": { "amount": ..., "daysBeforeCheckin": ... } would also be possible. You decide what you accept, what you treat as an array, and how you change from the form you got to the form you want.
I did this for the implementation.
csvData := make([][]string, 100)
for i := range csvData {
csvData[i] = make([]string, 100)
}
But I want to remove 100 since I don't know the actual size of the array. I want to push some string type elements into the 2d array. Basically I am reading a CSV file and want to extract its elements and store them in a 2d array. What would be a simple way to do so?
Here a working example, it creates a 10 by 10 slice.
package main
import (
"fmt"
)
func main() {
myData := "data"
var nestedSlice [][]string
nestedSize := 10
for i:=0;i<nestedSize; i++ {
jSlice := []string{}
for j:=0;j<nestedSize; j++ {
jSlice = append(jSlice, fmt.Sprintf("row:%v-col:%v-%v", i, j, myData))
}
nestedSlice = append(nestedSlice, jSlice)
}
fmt.Printf("result: %v\n", nestedSlice)
}
And here is the output showing the 10x10 slice.
result: [[row:0-col:0-data row:0-col:1-data row:0-col:2-data row:0-col:3-data row:0-col:4-data row:0-col:5-data row:0-col:6-data row:0-col:7-data row:0-col:8-data row:0-col:9-data] [row:1-col:0-data row:1-col:1-data row:1-col:2-data row:1-col:3-data row:1-col:4-data row:1-col:5-data row:1-col:6-data row:1-col:7-data row:1-col:8-data row:1-col:9-data] [row:2-col:0-data row:2-col:1-data row:2-col:2-data row:2-col:3-data row:2-col:4-data row:2-col:5-data row:2-col:6-data row:2-col:7-data row:2-col:8-data row:2-col:9-data] [row:3-col:0-data row:3-col:1-data row:3-col:2-data row:3-col:3-data row:3-col:4-data row:3-col:5-data row:3-col:6-data row:3-col:7-data row:3-col:8-data row:3-col:9-data] [row:4-col:0-data row:4-col:1-data row:4-col:2-data row:4-col:3-data row:4-col:4-data row:4-col:5-data row:4-col:6-data row:4-col:7-data row:4-col:8-data row:4-col:9-data] [row:5-col:0-data row:5-col:1-data row:5-col:2-data row:5-col:3-data row:5-col:4-data row:5-col:5-data row:5-col:6-data row:5-col:7-data row:5-col:8-data row:5-col:9-data] [row:6-col:0-data row:6-col:1-data row:6-col:2-data row:6-col:3-data row:6-col:4-data row:6-col:5-data row:6-col:6-data row:6-col:7-data row:6-col:8-data row:6-col:9-data] [row:7-col:0-data row:7-col:1-data row:7-col:2-data row:7-col:3-data row:7-col:4-data row:7-col:5-data row:7-col:6-data row:7-col:7-data row:7-col:8-data row:7-col:9-data] [row:8-col:0-data row:8-col:1-data row:8-col:2-data row:8-col:3-data row:8-col:4-data row:8-col:5-data row:8-col:6-data row:8-col:7-data row:8-col:8-data row:8-col:9-data] [row:9-col:0-data row:9-col:1-data row:9-col:2-data row:9-col:3-data row:9-col:4-data row:9-col:5-data row:9-col:6-data row:9-col:7-data row:9-col:8-data row:9-col:9-data]]
Depending on your use case there might be ways to optimise the for loop so its not n^2 time complexity but that's a different topic completely.
When creating an array or slice backed by new array you must supply a size, otherwise there is no way for the compiler to know how large to make it. But when declaring a variable to hold an array created elsewhere, just declare the var as a slice, type [][]string, which is the type of cvsData in your example.
I'm trying to define an array in struct in Go, devices array should have 3 items of type strings, but I can't find out how to print values of devices array
Below outputs "mismatched types string and [2]string". Any hints?
type Nodes struct {
Nodes []Node `json:"nodes"`
}
type Node struct {
devices [2]string `json:"devices"`
}
var nodes Nodes
fmt.Println("Device: %+v" + nodes.Nodes[i].devices)
Your error is because you're trying to concatenate a string and a [2]string:
"Device: %+v" + nodes.Nodes[i].devices
Specifically, "Device: %+v" is a string, and nodes.Nodes[i].devices is a [2]string.
But at higher level, this is the result of improperly using fmt.Println, made apparent by the use of a formatting verb %+v, which makes no sense in the context of Println. What you probably want is fmt.Printf:
fmt.Printf("Device: %+v\n", nodes.Nodes[0].devices)
You have to use fmt.Printf instead of Println :
fmt.Printf("Device: %+v", nodes.Nodes[i].devices)
Or you can do something like this :
for _, node := range nodes.Nodes {
for _, device := range node.devices {
fmt.Println("Device : " + device)
}
}
The output :
Device : Android
Device : iOS
I have problems using a array of structs inside another struct. The issue is that when I fill the structure with data from JSON data in the function below, it is filled correctly. When I directly try to access the data outside of the loop within a new loop the data is not there. So I guess that I'm filling the copied data structure instead of the reference to it so it's only valid inside the first loop. Though I have tried to allocate memory for it and still the same issue.
I guess that I failed somewhere and need directions. See some comments below in the code snippet.
type Spaces struct {
Items []*Space `json:"items"`
}
type Space struct {
Id string `json:"id"`
Messages []Message `json:"items"`
}
type Messages struct {
Items []Message `json:"items"`
}
// spaces are marshalled first so that there is a array of spaces
// with Id set. Then the function below is called.
func FillSpaces(space_id string) {
for _,s := range spaces.Items {
if s.Id == space_id {
// I tried to allocate with: s.Messages = &Messages{} without any change.
json.Unmarshal(f, &s) // f is JSON data
fmt.Printf(" %s := %v\n", s.Id, len(s.Messages))) // SomeId := X messages (everything seems fine!)
break
}
}
// Why is the messages array empty here when it was not empty above?
for _,s := range spaces.Items {
if s.Id == space_id {
fmt.Printf("%v", len(s.Messages))) // Length is 0!?
}
}
}
The application is unmarshaling to the variable s defined in the loop. Unmarshal to the slice element instead:
for i, s := range spaces.Items {
if s.Id == space_id {
err := json.Unmarshal(f, &spaces.Items[i]) // <-- pass pointer to element
if err != nil {
// handle error
}
break
}
}
So, I'm trying to get used to Go! and I've come up to a problem where I try making a new data type "RandomType" which contains a slice.
package main
type RandomType struct {
RandomSlice []int
}
func main() {
r := new(RandomType)
r.RandomSlice = make([]int, 0)
append(r.RandomSlice, 5)
}
This bit of code yields an error:
append(r.RandomSlice, 5) not used
However for instance if I try with
type RandomType struct {
RandomInt int
}
func main() {
r := new(RandomType)
r.RandomInt = 5
}
this works fine.
Not sure what I'm doing wrong.
append doesn't change the slice you provide but builds a new one.
You must use the returned slice :
r.RandomSlice = append(r.RandomSlice, 5)
More details about append in Effective Go and in the Go blog.