Instantiation of complex struct - go

I created a struct in a file called availability.go
package restconsume
import (
)
// Availabilityrequest for sabre
type Availabilityrequest struct {
OTAAirLowFareSearchRQ struct {
OriginDestinationInformation []struct {
DepartureDateTime string `json:"DepartureDateTime"`
DestinationLocation struct {
LocationCode string `json:"LocationCode"`
} `json:"DestinationLocation"`
OriginLocation struct {
LocationCode string `json:"LocationCode"`
} `json:"OriginLocation"`
RPH string `json:"RPH"`
} `json:"OriginDestinationInformation"`
POS struct {
Source []struct {
PseudoCityCode string `json:"PseudoCityCode" default:"F9CE"`
RequestorID struct {
CompanyName struct {
Code string `json:"Code" default:"TN"`
} `json:"CompanyName"`
ID string `json:"ID" default:"1"`
Type string `json:"Type" default:"1"`
} `json:"RequestorID"`
} `json:"Source"`
} `json:"POS"`
TPAExtensions struct {
IntelliSellTransaction struct {
RequestType struct {
Name string `json:"Name" default:"200ITINS"`
} `json:"RequestType"`
} `json:"IntelliSellTransaction"`
} `json:"TPA_Extensions"`
TravelPreferences struct {
TPAExtensions struct {
DataSources struct {
ATPCO string `json:"ATPCO" default:"Enable"`
LCC string `json:"LCC" default:"Disable"`
NDC string `json:"NDC" default:"Disable"`
} `json:"DataSources"`
NumTrips struct {
} `json:"NumTrips"`
} `json:"TPA_Extensions"`
} `json:"TravelPreferences"`
TravelerInfoSummary struct {
AirTravelerAvail []struct {
PassengerTypeQuantity []struct {
Code string `json:"Code"`
Quantity int `json:"Quantity"`
} `json:"PassengerTypeQuantity"`
} `json:"AirTravelerAvail"`
SeatsRequested []int `json:"SeatsRequested" default:"1"`
} `json:"TravelerInfoSummary"`
Version string `json:"Version" default:"1"`
} `json:"OTA_AirLowFareSearchRQ"`
}
// AddADepartureDate to set the date you leave
func (a *Availabilityrequest) AddADepartureDate() Availabilityrequest {
a.OTAAirLowFareSearchRQ.OriginDestinationInformation[0].DepartureDateTime = "2020-03-21"
return *a
}
//AddOriginDestination to set the ori and dest
func (a *Availabilityrequest) AddOriginDestination(Origin ,Destination string) {
a.OTAAirLowFareSearchRQ.OriginDestinationInformation[0].DestinationLocation.LocationCode = Destination
a.OTAAirLowFareSearchRQ.OriginDestinationInformation[0].OriginLocation.LocationCode = Origin
}
Now I've imported this package into my main one and having issue instatntiating with only one substruct(TPAExtensions)
main.go
package main
import (
"restconsume"
"fmt"
)
func main() {
var a= new(restconsume.Availabilityrequest)
a = Availabilityrequest{
"OTA_AirLowFareSearchRQ":OTAAirLowFareSearchRQ{
"IntelliSellTransaction": IntelliSellTransaction{
"RequestType": RequestType{
"Name": "200ITINS"},
},
},
}
}
error message
undefined: Availabilityrequest
My question is how could I instantiate this kind of complex struct?

The simplest answer is to not try to use struct literal but rather have a variable of the top-level type to be initialized to an appropriate zero value for its type and then explicitly set only those fields which are needed, like this:
var a Availabilityrequest
a.OTAAirLowFareSearchRQ.TPAExtensions.IntelliSellTransaction.RequestType.Name = "200ITINS"
But honestly, judging from your question, it looks like you're JavaScript programmer trying to attack Go without much prior knowledge about that language. This is a path to suffering.
Please be advised to at least start with the Tour of Go and then read any introductory-level book on Go (I would recommend this one).
"Effective Go" is also a must.

Related

How to define generic function with custom structs without listing all of them?

Let's say I have two different structs:
type One struct {
Id string
// Other fields
}
type Two struct {
Id string
// Other fields
}
Is it possible to define a function that accepts both One and Two without explicitly listing them as options?
E.g. I am looking for something like this:
type ModelWithId struct {
Id string
}
func Test[M ModelWithId](m M) {
fmt.PrintLn(m.Id)
}
one := One { Id: "1" }
Test(one) // Prints 1
I don't want to use funcTest[M One | Two](m M), because I'll likely have 10+ structs and I don't want to come back to the function every time I add a new struct to the codebase.
Generics constraints the type parameter behaviours using methods, so you need to rewrite your code as:
type One struct {
id string
}
func (o *One) Id() string {
return o.id
}
then your use site would become:
type ModelWithId interface {
Id() string
}
func Test[M ModelWithId](m M) {
fmt.Println(m.Id())
}

golang: declaring a camelcase in a struct declaration

I'm trying to read a yaml file via golang.
But the "matchLabels" sub-struct is not being recognized
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
app: test
spec:
replicas: 3
selector:
matchLabels:
app: web
struct
type myData struct {
Apivesion string `yaml:"apiVersion"`
Kind string
Metadata struct {
Name string
Labels struct {
App string
}
}
Spec struct {
Replicas int64
Selector struct {
Matchlabels struct {
App string
}
}
}
}
Expectation
&{apps/v1 Deployment {nginx-deploy {test}} {3 {{web}}}}
Result
&{apps/v1 Deployment {nginx-deploy {test}} {3 {{}}}}
Fix didn't work:
Matchlabels struct `yaml:"matchLabels"` {
Cerise Limón gave the answer in a comment:
Field tags follow the type:
Matchlabels struct { App string }
`yaml:"matchLabels"`
I don't think you implemented the suggested answer correctly, see where the tag is:
type myData struct {
Apivesion string `yaml:"apiVersion"`
Kind string
Metadata struct {
Name string
Labels struct {
App string
}
}
Spec struct {
Replicas int64
Selector struct {
Matchlabels struct {
App string
} `yaml:"matchLabels"`
}
}
}
See also: https://go.dev/play/p/yd9c-iBz2yL
type AutoGenerated struct {
APIVersion string `yaml:"apiVersion"`
Kind string `yaml:"kind"`
Metadata struct {
Name string `yaml:"name"`
Labels struct {
App string `yaml:"app"`
} `yaml:"labels"`
} `yaml:"metadata"`
Spec struct {
Replicas int `yaml:"replicas"`
Selector struct {
MatchLabels struct {
App string `yaml:"app"`
} `yaml:"matchLabels"`
} `yaml:"selector"`
} `yaml:"spec"`
}
You can use this tool, it is really helpful:
https://zhwt.github.io/yaml-to-go/

Golang - Missing expression error on structs

type Old struct {
UserID int `json:"user_ID"`
Data struct {
Address string `json:"address"`
} `json:"old_data"`
}
type New struct {
UserID int `json:"userId"`
Data struct {
Address string `json:"address"`
} `json:"new_data"`
}
func (old Old) ToNew() New {
return New{
UserID: old.UserID,
Data: { // from here it says missing expression
Address: old.Data.Address,
},
}
}
What is "missing expression" error when using structs?
I am transforming old object to a new one. I minified them just to get straight to the point but the transformation is much more complex. The UserID field for example works great. But when I use struct (which intended to be a JSON object in the end) the Goland IDE screams "missing expression" and the compiler says "missing type in composite literal" on this line. What I am doing wrong? Maybe should I use something else instead of struct? Please help.
Data is an anonymous struct, so you need to write it like this:
type New struct {
UserID int `json:"userId"`
Data struct {
Address string `json:"address"`
} `json:"new_data"`
}
func (old Old) ToNew() New {
return New{
UserID: old.UserID,
Data: struct {
Address string `json:"address"`
}{
Address: old.Data.Address,
},
}
}
(playground link)
I think it'd be cleanest to create a named Address struct.
You're defining Data as an inline struct. When assigning values to it, you must first put the inline declaration:
func (old Old) ToNew() New {
return New{
UserID: old.UserID,
Data: struct {
Address string `json:"address"`
}{
Address: old.Data.Address,
},
}
}
Hence it is generally better to define a separate type for Data, just like User.

Go - get parent struct

I'd like to know how to retrieve the parent struct of an instance.
I have no idea how to implement this.
For instance:
type Hood struct {
name string
houses []House
}
type House struct {
name string
people int16
}
func (h *Hood) addHouse(house House) []House {
h.houses = append(h.houses, house)
return h.houses
}
func (house *House) GetHood() Hood {
//Get hood where the house is situated
return ...?
}
Cheers
You should retain a pointer to the hood.
type House struct {
hood *Hood
name string
people int16
}
and when you append the house
func (h *Hood) addHouse(house House) []House {
house.hood = h
h.houses = append(h.houses, house)
return h.houses
}
then you can easily change the GetHood, although a getter may not be required at that point.
func (house *House) GetHood() Hood {
return *house.hood
}

How in Swift specify type constraint to be enum?

I want to specify a type constraint that the type should be a raw value enum:
enum SomeEnum: Int {
case One, Two, Three
}
class SomeProtocol<E: enum<Int>> { // <- won't compile
func doSomething(e: E) {
compute(e.toRaw())
}
}
How can I do it in Swift? (I used the F# syntax for example)
enum SomeEnum: Int {
case One, Two, Three
}
class SomeClass<E: RawRepresentable where E.RawValue == Int>{
func doSomething(e: E) {
print(e.rawValue)
}
}
class SomeEnumClass : SomeClass<SomeEnum> {
}
or directly
class SomeOtherClass{
func doSomething<E: RawRepresentable where E.RawValue == Int>(e: E) {
print(e.rawValue)
}
}
UPDATE for swift3:
enum SomeEnum: Int {
case One, Two, Three
}
class SomeClass<E: RawRepresentable> where E.RawValue == Int {
func doSomething(e: E) {
print(e.rawValue)
}
}
class SomeEnumClass : SomeClass<SomeEnum> {
}
resp.
class SomeOtherClass{
func doSomething<E: RawRepresentable>(e: E) where E.RawValue == Int {
print(e.rawValue)
}
}
While you can place enums into a generic type without contraints (<T>), it's not possible to create constraints for all enums or all structs. All the constraints are based on interfaces (subclassing, protocols). Unfortunately, there is nothing in common between two random structs or two random enums.
Structs and enums can't inherit from other structs/enums so the only constraints for enums must be based on protocols.
protocol EnumProtocol {
func method()
}
enum TestEnum : Int, EnumProtocol {
case A
case B
func method() {
}
}
enum TestEnum2 : Int, EnumProtocol {
case C
func method() {
}
}
class EnumGeneric <T : EnumProtocol> {
func method(a: T) {
a.method()
}
}
let test = EnumGeneric<TestEnum>()
test.method(TestEnum.A)
Also note that all enums "inheriting" from a primitive type like Int conform to RawRepresentable, so you could
class EnumGeneric <T : RawRepresentable> {
func method(a: T) {
println("\(a.toRaw())");
}
}
but that won't work for enums declared as enum TestEnum {
AFAIK, Swift does not support type constraint to be specified with enums.
Cited from Swift Manual
Type Constraint Syntax
You write type constraints by placing a single class or protocol
constraint after a type parameter’s name, separated by a colon, as
part of the type parameter list. The basic syntax for type constraints
on a generic function is shown below (although the syntax is the same
for generic types):
Strictly limited to a class or protocol unless there's some hidden features which is not mentioned in manual. As far as I tested, struct or enum are all prohibited by the compiler.
enum Test1 : Int
{
case AAA = 0
}
func test1f<T:Test1>(a: Test1) {} // error: Inheritance from non-protocol, non-class type 'Test1'
struct Test2
{
var aaa:Int = 0
}
func test2f<T:Test2>(a: Test2) {} // error: Inheritance from non-protocol, non-class type 'Test1'
class Test3
{
}
func test3f<T:Test3>(a: Test3) {} // OK

Resources