Is there a good way to embed initialized struct variables in another struct?
Consider the following situation:
type Account struct {
AdminUser, AdminPass string
}
const (
acc1: "account_user",
pass: "111222"
)
var AccountDef = Account {
AdminUser: "acc1",
AdminPass: "pass1"
}
type Login struct {
Acc *AccountDef
Username, Password, Token string
}
var LoginDef = Login {
Token: "adaasdasddas1123"
}
I want to reuse AccountDef in Login, then I want to instantiate LoginDef in another function then use it for rendering templates like LoginDef.Acc.AdminUser
Is this possible to do?
If you want a Login to contain the fields from an Account, you can embed them like so:
http://play.golang.org/p/4DXnIsILd6
type Account struct {
AdminUser string
AdminPass string
}
type Login struct {
*Account
Username, Password, Token string
}
func main() {
acct := &Account{
AdminUser: "username",
AdminPass: "pass",
}
login := Login{Account: acct}
fmt.Println("login.AdminUser:", login.AdminUser)
fmt.Println("login.AdminPass:", login.AdminPass)
}
Related
I am creating an auth flow for my mobile app. I received an error: "Cannot find user in scope" on "self.userSession = user" & ".document(.user.uid)" I'm not sure how to resolve this error. Any help would be appreciated!
`
import SwiftUI
import Firebase
import FirebaseCore
import FirebaseAuth
import FirebaseStorage
import FirebaseFirestore
import FirebaseFirestoreSwift
class AuthViewModel: ObservableObject {
#Published var userSession: FirebaseAuth.User?
init() {
self.userSession = Auth.auth().currentUser
print("DEBUG: User session is \(self.userSession?.uid)")
}
func login(withEmail email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password) { result, error in
if let error = error {
print("DEBUG: Failed to sign in with error \(error.localizedDescription)")
return
}
guard let user = result?.user else { return }
self.userSession = user
print("DEBUG: Did log user in..")
}
}
func register(withEmail email: String, password: String, fullname: String) {
Auth.auth().createUser(withEmail: email, password: password) { result, error in
if let error = error {
print("DEBUG: Failed to register with error \(error.localizedDescription)")
return
}
print("DEBUG: Registered user successfully.")
print("DEBUG: User is \(self.userSession)")
let data = ["email": email,
"fullname": fullname,
"uid": user.uid]
Firestore.firestore().collection("users")
.document(user.uid)
.setData(data) { _ in
print("DEBUG: Did upload user data..")
}
}
}
func signOut() {
// sets user session to nil so we show login view
userSession = nil
// signs user out on server
try? Auth.auth().signOut()
}
}
`
I have tried moving the declaration up on to the viewmodel but that caused another error: "cannot find result in scope".
You should use an auth state change listener to save user session as mentioned in the Firebase documentation. You should also not initialize the auth object every time in every function.
import FirebaseAuth
class AuthViewModel: Observable Object {
private let auth: Auth = Auth.auth() // You can also use dependency injection
#Published var userSession: User?
private var authStatusHandler: AuthStateDidChangeListenerHandle?
func addAuthStatusListener() {
if let handle = authStatusHandler {
auth.removeStateDidChangeListener(handle)
}
authStatusHandler = auth.addStateDidChangeListener { _, user in
self.userSession = user
}
}
...
}
In the register function, you try to access the "user" variable which is defined in the login function. This variable is out of the scope of the register function. You should use the userSession in the class for the register function.
func register(withEmail email: String, password: String, fullname: String) {
...
let data = ["email": email,
"fullname": fullname,
"uid": userSession.uid] // <- Here
Firestore.firestore().collection("users")
.document(userSession.uid) // <- Here
.setData(data) { _ in
print("DEBUG: Did upload user data..")
}
...
}
In my golang code, I use net/http and gorilla mux.
In the function below, when I encode the nested structure variable, the http response shows blank "{}". However, if I encode only one of the non-nested struct's they show up ok.
Can you please help how I can send the nested-structure in http-response? Thank you
func getNestedStruct(w http.ResponseWriter, r *http.Request) {
type User1 struct {
ID int `json:"Id1"`
Email string `json:"Email1"`
Password string `json:"Password1"`
}
type User2 struct {
ID int `json:"Id2"`
Email string `json:"Email2"`
}
type Users struct {
MyUser1 User1 `json:"User1"`
MyUser2 User2 `json:"User1"`
}
var myUser1 User1
var myUser2 User2
var myUsers Users
myUser1.ID = 1
myUser1.Email = "user1#email.com"
myUser1.Password = "user1"
myUser2.ID = 2
myUser2.Email = "user2#email.com"
myUsers.MyUser1 = myUser1
myUsers.MyUser2 = myUser2
// these print without issues
log.Printf("getNestedStruct: Struct User1: ", myUser1)
log.Printf("getNestedStruct: Struct User2: ", myUser2)
log.Printf("getNestedStruct: Nested Struct Users: ", myUsers)
// This does not work --> shows {} in http response
json.NewEncoder(w).Encode(myUsers)
// This works:
//json.NewEncoder(w).Encode(myUser1)
}
MyUser1 & MyUser2 both have the same JSON key. Giving different keys should work
type Users struct {
MyUser1 User1 `json:"User1"`
MyUser2 User2 `json:"User2"`
}
In one view, I have this func to signUp and get userName
func signUp() {
if self.email != "" {
if self.password == self.repass {
session.signUp(email: email, password: password) { (result, error) in
if error != nil {
self.error = error!.localizedDescription
//self.error = "A senha deve ter 6 caracteres ou mais"
}
else{
self.email = ""
self.password = ""
let db = Firestore.firestore()
db.collection("Users").document(result!.user.uid).setData(["userName": userName]) { (error) in
if error != nil{
}
}
}
}
}
else{
self.error = "Senhas não coincidem"
}
}
else{
self.error = "Complete todos espaços"
}
}
In other view, I want to get the userName the user typed ad display it, but for this I need to link both views to get access to func SignUp. How to do it?
EDIT:
Based on the answer I was given, I did the corresponding changes:
SessionStore:
#Published var session: User? = nil
var handle: AuthStateDidChangeListenerHandle?
#Published var userName: String = ""
func listen() {
handle = Auth.auth().addStateDidChangeListener({ [self] (auth, user) in
if let user = user {
self.session = User(uid: user.uid, email: user.email!, userName: userName)
}
else {
self.session = nil
}
})
}
struct User {
var uid:String
var email:String
var userName: String
}
HomeView ----> var userName: User
Text(userName.userName)
explaining how my code works: the #main view is MedAppApp: App. From there, the code goes to ContentView. if session.session != nil, TransitionView, else, SignView. Continuing from SignView, there I have both SignInView and SignUpView views, which they have Button(action: signIn) and Button(action: Signup), respectively. Continuing from TransitionView, there is where I have:
struct TransitionView: View {
#StateObject var LocationModel = LocationViewModel()
#State var userName = User(uid: "", email: "", userName: "")
var body: some View {
HomeView(LocationModel: LocationModel, userName: userName)
}
}
#State var userName =... and userName: userName needed to be added
The app launches, I can signUp with username (and its stored in Firestore with uid as document), but the userName isn't displayed. I think the problem must be in User(uid: "", email: "", password: ""). I didn't know what to add there.
By the way, Im thinking about maintaining the code and then get the userName by using the document id (that already is the user uid) so I can access it. Don't have a final answer yet, but Im working on it.
EDIT2:
I added #StateObject var session = SessionStore()
Tried to use:
#State var userName = User(uid: SessionStore().session?.uid ?? "", email: SessionStore().session?.email ?? "", userName: SessionStore().session?.userName ?? "")
Still doesn't work
Your question is too open-ended, but I'll provide an answer that hopefully will set you up on the right direction.
First, in SwiftUI, separate the concept of a view (i.e. how things are arranged on the screen) from the concept of data that drives the views. What I mean by that is, if you need some data, like userName, the code that obtains it shouldn't know or care about which view will make use of it. And Views, shouldn't care how the data is obtained.
Second, in SwiftUI, views should not be thought of as "entities" (like in UIKit) with their own life cycles. They are just declarative statements that define how the UI is arranged.
For example, suppose you have this (fake) class that signs the user in, and when signed-in, populates the userName property. The instance of this class is a view model.
struct User {
let userName: String
}
class Session: ObservableObject {
#Published var user: User? = nil
func signIn(_ completion: (User) -> ()) {
DispatchQueue.main.asyncAfter(.now() + 0.5) {
self.user = User(userName: "Mateus") // fake sign-in
completion(self.user) // not really used in this example
}
}
}
#Published and ObservableObject in combination are how SwiftUI views know to react to changes to this object. Read more about them, if you don't know what they do.
Next, design a root view that decides what inner view to display depending on whether the user is signed in or not:
struct RootView: View {
#StateObject var session = Session()
var body: some View {
VStack() {
if let user = session.user {
ContentView(user: user) // view is conditionally rendered
} else {
Button("sign in") { self.signIn() }
}
}
}
func signIn() {
self.session.signIn() {
print("signed in...!")
}
}
}
#StateObject manages the life cycle of the view model for the view.
As you see above, ContentView will only be rendered when session.user is not nil (i.e. when user has signed in), so the view is driven by changes in data. I did not need to create a ContentView instance anywhere ahead of time.
Then ContentView is straightforward:
struct ContentView: View {
var user: User
var body: some View {
Text("signed-in username: \(user.userName)")
}
}
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.
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.