Golang array of string inside struct - go

Im using the following struct
type Str struct {
Info string
Command string
}
And to fill data inside of it Im doing the following which works.
return []Str{
{"info from source",
"install && run"},
}
Now I need to change the command to array
type Str struct {
Info string
Command []string
}
And provide each of the commands("install" and "run") in new entry in the array, how can I do that
when I try with
return []Str{
{"info from source",string[]{
{"install}, {"run"}},
}
I got erorr of missing type literal, any idea what Im doing wrong

The correct syntax is the following:
return []Str{
{"info from source", []string{"install", "run"}},
}

Related

How can I get this type of data in Go lang?

This is API response data, looks like this.
{
"result":1,
"message":"",
"pds": [
{
"state":"Y",
"code":13,
"name":"AAA",
"price":39900,
},
{
"state":"Y",
"code":12,
"name":"BBB",
"price":38000,
}
],
"request":
{
"op":"new",
}
}
How can I get this data in Go lang?
I tried json.Unmarshall and get with map[string]interface{} but it looks like I used the wrong type to get the data.
Should I use structure??
You need to create a struct to handle this properly if you don't want the json.Unmarshall output to be a map[string]interface{}.
If you map this JSON object to a Go struct you find the following structure:
type APIResponse struct {
Result int `json:"result"`
Message string `json:"message"`
Pds []struct {
State string `json:"state"`
Code int `json:"code"`
Name string `json:"name"`
Price float64 `json:"price"`
} `json:"pds"`
Request struct {
Op string `json:"op"`
} `json:"request"`
}
You also can find a great tool to convert JSON objects to Go structs here
If you don't want to use the native json.Unmarshall, here's a good option to use the package go-simplejson.
Documentation

How to parse strings of json object seperated by comma but not enclosed by array

In the below sample elasticsearch doument created by the alerting rule, contains 3 comma seperated string of json objects under hits but they are NOT contained in an array [], so in Go unable to parse them.
Can someone help me parse the hits documents
[map[_id:2s3kfXoB2vuM1J-EwpE7 _index:alert-X _score:%!s(float64=1)
_source:
map[#timestamp:2021-07-06T22:16:21.818Z
alert_name:alert events login
hits:
{"_index":".ds-logs-events-2021.06.30-000005","_type":"_doc","_id":"S83kfXoB2vuM1J-Eo4_v", ...
{"_index":".ds-logs-events-2021.06.30-000005","_type":"_doc","_id":"Ss3kfXoB2vuM1J-Eo4_v",...
{"_index":".ds-logs-events-2021.06.30-000005","_type":"_doc","_id":"N83kfXoB2vuM1J-EiI2l",...
rule_id:cfb85000-db0e-11eb-83e0-bb11d01642c7
]
Model
type Alert struct {
Alert string `json:"alert_name"`
Hits []*Event `json:"hits"`
}
type Event struct {
Model string
Action string
}
Following offical example
Using official go-elasticsearch and easyjson
Concatenated the json string with the array block and was able to Unmarshal it
hitsArray := "[" + alert.Source.Hits + "]"
var hits []model.AlertHits
json.Unmarshal([]byte(hitsArray), &hits)
for _, hit := range hits {
log.Printf("hit %s action %s", hit.ID, hit.Source.Message.Action)
}
model.go
type AlertHits struct {
ID string `json:"_id"`
Source Event `json:"_source"`
}
type Event struct {
Message Message `json:"message"`
}
type Message struct {
Action string `json:"action"`
Model string `json:"model"`
}

How do I append to all string values inside a struct?

I have a struct defined in fruits.go
package domain
type AppleImages struct {
Front string `json:"frontImage"`
Back string `json:"backImage"`
Top string `json:"topImage"`
}
And I defined the same in process.go (which returns this data to the handler). This definition is only for demonstration purposes since I'm getting values from the database using gorm so we cannot append the required URL here.
package process
func getApple() (apple domain.Apple){
apple = domain.Apple{
Front: "front-image.png"
Back: "back-image.png"
Top: "top-image.png"
}
return
}
For my output is want to return
{
frontImage: "https://www.example.com/front-image.png",
backImage: "https://www.example.com/back-image.png",
topImage: "https://www.example.com/top-image.png",
}
I don't want to manually add https://www.example.com/ to each of the images in the struct.
Is there a way of parsing through the struct and automatically appending this string to all existing values?
Use gorm AfterFind hook. Every time after load data from database gorm call AfterFind and your data will be updated for Apple model. Then you don't need to manually do it after every time fetching from the database.
func (u *Apple) AfterFind() (err error) {
u.Front= "https://www.example.com/"+ u.Front
u.Back= "https://www.example.com/"+ u.Back
u.Top= "https://www.example.com/"+ u.Top
return
}
See details here
Is there a way of parsing through the struct and automatically appending this string to all existing values?
No.
I don't want to manually add https://www.example.com/ to each of the images in the struct.
Go provides no magic for thing to happen without you programming it. You must do this "manually".
You could use reflect to add a prefix for each filed in the struct.
See details here.
func getApple() (apple domain.Apple) {
apple = domain.Apple{
Front: "front-image.png",
Back: "back-image.png",
Top: "top-image.png",
}
addURL(&apple, "https://www.example.com/")
//fmt.Println(apple)
return
}
func addURL(apple *domain.Apple, url string) {
structValue := reflect.ValueOf(apple).Elem()
for i := 0; i < structValue.NumField(); i++ {
fieldValue := structValue.Field(i)
// skip non-string field
if fieldValue.Type().Kind() != reflect.String {
continue
}
structValue.Field(i).SetString(url + fieldValue.String())
}
}

Better way of decoding json values

Assume a JSON object with the general format
"accounts": [
{
"id": "<ACCOUNT>",
"tags": []
}
]
}
I can create a struct with corresponding json tags to decode it like so
type AccountProperties struct {
ID AccountID `json:"id"`
MT4AccountID int `json:"mt4AccountID,omitempty"`
Tags []string `json:"tags"`
}
type Accounts struct {
Accounts []AccountProperties `json:"accounts"`
}
But the last struct with just one element seems incorrect to me. Is there a way I could simply say type Accounts []AccountProperties `json:"accounts"` instead of creating an entire new struct just to decode this object?
You need somewhere to store the json string accounts. Using a:
var m map[string][]AccountProperties
suffices, though of course you then need to know to use the string literal accounts to access the (single) map entry thus created:
type AccountProperties struct {
ID string `json:"id"`
MT4AccountID int `json:"mt4AccountID,omitempty"`
Tags []string `json:"tags"`
}
func main() {
var m map[string][]AccountProperties
err := json.Unmarshal([]byte(data), &m)
fmt.Println(err, m["accounts"])
}
See complete Go Playground example (I had to change the type of ID to string and fix the missing { in the json).
As Dave C points out in comments, this is no shorter than just using an anonymous struct type:
var a struct{ Accounts []AccountProperties }
in terms of the Unmarshall call (and when done this way it's more convenient to use). Should you want to use an anonymous struct like this in a json.Marshall call, you'll need to tag its single element to get a lowercase encoding: without a tag it will be called "Accounts" rather than "accounts".
(I don't claim the map method to be better, just an alternative.)

how tags of struct fields are used?

I do not understand how field tags in struct are used and when. Per https://golang.org/ref/spec#Struct_types:
[tag] becomes an attribute for all the fields in the corresponding field declaration
what does this mean?
[tag] becomes an attribute for all the fields in the corresponding field declaration
In addition to the links above ("What are the use(s) for tags in Go?", "go lang, struct: what is the third parameter") this thread provides an example which does not come from the standard packages:
Suppose I have the following code (see below). I use a type switch the check the type of the argument in WhichOne().
How do I access the tag ("blah" in both cases)?
I'm I forced the use the reflection package, or can this also be done in "pure" Go?
type PersonAge struct {
name string "blah"
age int
}
type PersonShoe struct {
name string "blah"
shoesize int
}
func WhichOne(x interface{}) {
...
}
After reading that (again), looking in json/encode.go and some trial and error, I have found a solution.
To print out "blah" of the following structure:
type PersonAge struct {
name string "blah"
age int
}
You'll need:
func WhichOne(i interface{}) {
switch t := reflect.NewValue(i).(type) {
case *reflect.PtrValue:
x := t.Elem().Type().(*reflect.StructType).Field(0).Tag
println(x)
}
}
Here: Field(0).Tag illustrates the "becomes an attribute for all the fields in the corresponding field declaration".

Resources