-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path8.structs.go
220 lines (195 loc) · 9.48 KB
/
8.structs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package main
import (
"fmt"
)
// Declaring a struct variable.
// If we need multiple struct variables we need to declare multiple struct varibales as below
// for each struct variable we want
var mystruct1 struct{
x int
y string
z bool
}
// Creating a struct type
// By creating a new struct type we can create multiple varibales based on this struct type
type mystruct struct{
x int
y string
z bool
}
// Adding a struct as a field on another custom-defined type
// Accessing elements in nested structs is a bit tedious
// So we should use a different concept in GO called Anonymous struct fields
type nestedStruct struct{
a int
b bool
c mystruct
}
// Anonymous struct fields
// we can now directly access the elements of inner struct (mystruct)
// as if they are fields of outer struct (anonyStruct i.e. anonyStruct.x, anonyStruct.y etc.;)
type anonyStruct struct{
a int
b bool
mystruct
}
func main(){
mystruct1.x = 1
mystruct1.y = "Bharath"
mystruct1.z = true
fmt.Printf("mystruct1 = %v\nGo Representation %#[1]v\n", mystruct1)
// Accessing struct variable elements
fmt.Println("mystruct1.x =", mystruct1.x, "; mystruct1.y =", mystruct1.y,
"; mystruct1.z =", mystruct1.z)
fmt.Println("--------------------------------")
// Declaring a varibale on custom-defined type mystruct and using struct literals
// In declaration like below, the order of field values are important and
// should be matched with order of custom-defined type fields
// This type of declaration of field values is only good if you know value of every field beforehandedly
// Otherwise, if you only want to set some field values initially
// its better to use mystruct{x:1, y:"Bharath", z:true} syntax
mystruct2 := mystruct{1, "Bharath", true}
fmt.Printf("mystruct2 = %v\nGo Representation %#[1]v\n", mystruct2)
// Accessing struct variable elements
fmt.Println("mystruct2.x =", mystruct2.x, "; mystruct2.y =", mystruct2.y,
"; mystruct2.z =", mystruct2.z)
fmt.Println("--------------------------------")
// Other Method to declare field values using struct literal
// In declaration like below, the order of field values is not important
// Mixture of both declarations like this (mystruct{1, y: "Bharath", z: true}) would not work
mystruct21 := mystruct{y: "Bharath", x: 1, z: true}
fmt.Printf("mystruct21 = %v\nGo Representation %#[1]v\n", mystruct21)
fmt.Println("--------------------------------")
// Leaving some field values in struct literal while declaration like below
// This syntax works mystruct{x: 1, y: "Bharath"}
// but this doesn't work mystruct{1, "B"} or mystruct{1, z:true} etc.;
mystruct22 := mystruct{x: 1}
fmt.Printf("mystruct22 = %v\nGo Representation %#[1]v\n", mystruct22)
fmt.Println("--------------------------------")
// our varibale mystruct2 of type mystruct is passed as argument to showInfo() function
mystruct3 := showInfo(mystruct2)
fmt.Println("Passed mystruct2 argument is returned and stored in mystruct3 and is =",mystruct3)
fmt.Println("--------------------------------")
mystruct4 := mystruct{1, "Bharath", true}
fmt.Println("Before calling modified(&mystruct4), mystruct4 =", mystruct4)
modified(&mystruct4)
fmt.Println("After calling modified(&mystruct4), mystruct4 =", mystruct4)
fmt.Println("--------------------------------")
// Declaring nestedstruct varibale using struct literal
// If we want we can also omit declaring some field values and those will be set to their zero values
// For ex: nestedStruct{a:1} = {1, false, {0, "", false}}
nestedStruct1 := nestedStruct{1, true, mystruct{1, "Bharath", true}}
fmt.Printf("nestedStruct1 = %v\nGo Representation %#[1]v\n", nestedStruct1)
// Accessing or setting elements on nested structs is a bit tedious
// So we should use a different concept in GO called Anonymous struct fields
fmt.Println("nestedStruct1.a =", nestedStruct1.a, "nestedStruct1.b =", nestedStruct1.b,
"nestedStruct1.c =", nestedStruct1.c)
// If we further access nestedStruct1.c values which is itslef a struct
fmt.Println("nestedStruct1.c.x =", nestedStruct1.c.x, "nestedStruct1.c.y =", nestedStruct1.c.y,
"nestedStruct1.c.z =", nestedStruct1.c.z)
fmt.Println("--------------------------------")
// Declaring anonyStruct variable using a struct literal
anonyStruct1 := anonyStruct{1, true, mystruct{1, "Bharath", true}}
fmt.Printf("anonyStruct1 = %v\nGo Representation %#[1]v\n", anonyStruct1)
// Accessing or setting elements on nested structs is now easy with anonymous struct fields
fmt.Println("anonyStruct1.a =", anonyStruct1.a, "anonyStruct1.b =", anonyStruct1.b,
"anonyStruct1.mystruct =", anonyStruct1.mystruct)
// If we want to further access anonyStruct1.mystruct values which is itslef a struct
// we can now directly access the elements of inner struct (mystruct)
// as if they are fields of outer struct (anonyStruct i.e. anonyStruct.x, anonyStruct.y etc.;)
fmt.Println("anonyStruct1.x =", anonyStruct1.x, "anonyStruct1.y =", anonyStruct1.y,
"anonyStruct1.z =", anonyStruct1.z)
fmt.Println("--------------------------------")
// How to copy structs type of one variable to other varibale and How it internally works?
// To understand this, go to copyStructs() function where we performed both normal copy and
// deep copy
copyStructs()
fmt.Println("--------------------------------")
// How to assign a struct field in map
fmt.Println("One way of Assigning a struct field in map")
temp1 := map[string]mystruct{"item1":mystruct{1, "bharath", true}}
fmt.Printf("Before assigning a struct field in map, temp1 = %#v\n", temp1)
// The below code will return an error saying:
// Error: cannot assign to struct field temp1["item1"].z in map
// temp1["item1"].z = false
// One way of doing it is:
fmt.Println("By checking if key is in map or not")
if temp2, ok := temp1["item1"]; ok {
temp2.z = false
temp1["item1"] = temp2
}
fmt.Printf("After assigning a struct field in map, temp1 = %#v\n", temp1)
fmt.Println("--------------------------------")
// The other way of doing it is: make your map a map of pointers to structs.
// The disadvantage with this method is you can't see struct values when printed, instead we
// see pointer address to this struct.
fmt.Println("Other way of Assigning a struct field in map")
fmt.Println("Using pointer to structs in a map")
temp2 := map[string]*mystruct{"item1": &mystruct{1, "bharath", true}}
fmt.Printf("Before assigning a struct field in map, temp2 = %#v\n", temp2)
fmt.Println("Assigning to a struct field in a map, temp2['item1'].z = false")
temp2["item1"].z = false
fmt.Printf("After assigning a struct field in map, temp2 = %#v\n", temp2)
// If in map[string]mystruct, mystruct itself is a map, bool = mystruct{map[string]int, bool};
// We can directly assign map values in mystruct, and no need of doing as above for bool
fmt.Println("--------------------------------")
type exstruct struct {
m map[string]int
b bool
}
temp3 := map[string]exstruct{"v1":exstruct{map[string]int{"v2":0}, false}}
fmt.Printf("Before assigning to a map value in a struct field in map, temp3 = %#v\n", temp3)
// From above discussions, we can't perform assignment of temp3["v1"].b = true and lead to error
// But we can directly assign to map values in struct;
// For ex, temp3["v1"].m["v2"] = 1 is perfectly valid
fmt.Println("Assigning to a map value in a struct field which is itself in map,\ntemp3['v1'].m['v2'] = 1")
temp3["v1"].m["v2"] = 1
fmt.Printf("After assigning to a map value in a struct field in map, temp3 = %#v\n", temp3)
}
// function on custom-defined type
// i.e. custome-defined type is passed as argument to this function
func showInfo(m mystruct) mystruct {
fmt.Println("mystruct2 passed as argument to showInfo() and is =", m)
return m
}
// function
func modified(m *mystruct){
// we don't need to use pointer (i.e. *m) to set x, y, z fields.
// If we pass a pointer, Go is able to understand directly while accessing fields of any struct
// as if it is a direct access rather a pointer access.
// But even here if we want to use pointer to access those fields, we need to use
// (*m).x, (*m).y etc., All these are equivalent to accessing fields directly using m.x, m.y etc.;
// We shouldn't use *m.x, *m.y etc. because Go considers it as m.x has a pointer and
// then looks for pointer value in m.x which is not the case in our example.
m.x = 2
m.y = "Talluri"
m.z = false
fmt.Println("In modified() function and is =",m)
}
func copyStructs(){
type point2d struct{
x float64
y float64
}
type points struct{
p []point2d
}
v := points{[]point2d{point2d{2, 3}, point2d{12, 30}, point2d{40, 50}, point2d{5, 1},
point2d{12, 10}, point2d{3, 4}, point2d{6, 2}}}
fmt.Printf("Go Representation = %#v\n", v)
fmt.Println("v =", v)
fmt.Println("------Performing Normal Copy (normalCopy := v)------")
normalCopy := v
fmt.Printf("normalCopy = %v\n", normalCopy)
fmt.Println("(&normalCopy == &v) =", &normalCopy == &v)
fmt.Println("(&normalCopy.p == &v.p) =", &normalCopy.p == &v.p)
fmt.Println("(&normalCopy.p[0] == &v.p[0]) =", &normalCopy.p[0] == &v.p[0])
fmt.Println("------Performing Deep Copy using copy() function------")
temp := make([]point2d, len(v.p))
copy(temp, v.p)
deepCopy := points{temp}
fmt.Printf("deepCopy = %v\n", deepCopy)
fmt.Println("(&deepCopy == &v) =", &deepCopy == &v)
fmt.Println("(&deepCopy.p == &v.p) =", &deepCopy.p == &v.p)
fmt.Println("(&deepCopy.p[0] == &v.p[0]) =", &deepCopy.p[0] == &v.p[0])
}