Pisanie interfejsu API banku
Teraz, gdy utworzyliśmy podstawową logikę banku online, skompilujmy internetowy interfejs API, aby przetestować go z przeglądarki (a nawet wiersza polecenia). Na razie nie będziemy używać bazy danych do utrwalania danych, więc musimy utworzyć zmienną globalną do przechowywania wszystkich kont w pamięci.
Ponadto pominiemy część testowania, aby uniknąć zbyt długiego przechowywania tego przewodnika. W idealnym przypadku należy postępować zgodnie z tym samym podejściem, które wykonaliśmy podczas kompilowania pakietu podstawowego w celu pisania testów przed kodem.
Konfigurowanie konta w pamięci
Zamiast używać bazy danych do utrwalania danych, użyjemy mapy pamięci dla kont, które utworzymy podczas uruchamiania programu. Ponadto użyjemy mapy, aby uzyskać dostęp do informacji o koncie przy użyciu numeru konta.
Przejdź do $GOPATH/src/bankapi/main.go
pliku i dodaj następujący kod, aby utworzyć zmienną globalną accounts
i zainicjować ją przy użyciu konta. (Ten kod jest podobny do tego, co zrobiliśmy podczas tworzenia testów wcześniej).
package main
import (
"github.com/msft/bank"
)
var accounts = map[float64]*bank.Account{}
func main() {
accounts[1001] = &bank.Account{
Customer: bank.Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
}
}
Upewnij się, że jesteś w $GOPATH/src/bankapi/
lokalizacji. Uruchom program za pomocą polecenia go run main.go
, aby upewnić się, że nie masz żadnych błędów. Na razie program nie robi nic innego, więc dodajmy logikę w celu utworzenia internetowego interfejsu API.
Uwidaczniaj metodę instrukcji
Tworzenie internetowego interfejsu API w języku Go jest łatwe, jak pokazano w poprzednim module. Będziemy nadal korzystać z net/http
pakietu. Użyjemy również HandleFunc
funkcji i ListenAndServe
, aby uwidocznić punkty końcowe i uruchomić serwer. Funkcja HandleFunc
wymaga nazwy ścieżki adresu URL, którą chcesz uwidocznić, oraz nazwy funkcji z logiką dla tego punktu końcowego.
Zacznijmy od ujawnienia funkcji drukowania instrukcji dla konta. Skopiuj i wklej następującą funkcję w pliku main.go
:
func statement(w http.ResponseWriter, req *http.Request) {
numberqs := req.URL.Query().Get("number")
if numberqs == "" {
fmt.Fprintf(w, "Account number is missing!")
return
}
if number, err := strconv.ParseFloat(numberqs, 64); err != nil {
fmt.Fprintf(w, "Invalid account number!")
} else {
account, ok := accounts[number]
if !ok {
fmt.Fprintf(w, "Account with number %v can't be found!", number)
} else {
fmt.Fprintf(w, account.Statement())
}
}
}
Pierwszym wyróżnieniem statement
funkcji jest to, że otrzymuje obiekt w celu zapisania odpowiedzi z powrotem do przeglądarki (w http.ResponseWriter
). Otrzymuje on również obiekt żądania w celu uzyskania dostępu do informacji z żądania HTTP (req *http.Request
).
Następnie zwróć uwagę, że używamy req.URL.Query().Get()
funkcji do odczytywania parametru z ciągu zapytania. Ten parametr jest numerem konta, który wyślemy za pośrednictwem wywołania HTTP. Użyjemy tej wartości, aby uzyskać dostęp do mapy konta i uzyskać jej informacje.
Ponieważ otrzymujemy dane od użytkownika, należy uwzględnić pewne weryfikacje, aby uniknąć awarii. Gdy wiemy, że mamy prawidłowy numer konta, możemy wykonać wywołanie Statement()
metody i wyświetlić ciąg, który powróci do przeglądarki (fmt.Fprintf(w, account.Statement())
).
Teraz zmodyfikuj main()
funkcję tak, aby wyglądała następująco:
func main() {
accounts[1001] = &bank.Account{
Customer: bank.Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
}
http.HandleFunc("/statement", statement)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
Jeśli nie widzisz żadnego błędu lub danych wyjściowych podczas uruchamiania programu (go run main.go
), działa on poprawnie. Otwórz przeglądarkę internetową i wprowadź adres URL http://localhost:8000/statement?number=1001
lub uruchom następujące polecenie w innej powłoce, gdy program jest uruchomiony:
curl http://localhost:8000/statement?number=1001
Powinny zostać wyświetlone następujące dane wyjściowe:
1001 - John - 0
Uwidaczniaj metodę depozytu
Kontynuujmy korzystanie z tego samego podejścia, aby uwidocznić metodę depozytu. W tym przypadku chcemy dodać pieniądze na konto, które mamy w pamięci. Za każdym razem, gdy wywołujemy metodę Deposit()
, należy zwiększyć saldo.
W głównym programie dodaj funkcję podobną deposit()
do poniższej. Funkcja pobiera numer konta z ciągu zapytania, sprawdza, czy konto istnieje na accounts
mapie, sprawdza, czy kwota depozytu jest prawidłową liczbą, a następnie wywołuje metodę Deposit()
.
func deposit(w http.ResponseWriter, req *http.Request) {
numberqs := req.URL.Query().Get("number")
amountqs := req.URL.Query().Get("amount")
if numberqs == "" {
fmt.Fprintf(w, "Account number is missing!")
return
}
if number, err := strconv.ParseFloat(numberqs, 64); err != nil {
fmt.Fprintf(w, "Invalid account number!")
} else if amount, err := strconv.ParseFloat(amountqs, 64); err != nil {
fmt.Fprintf(w, "Invalid amount number!")
} else {
account, ok := accounts[number]
if !ok {
fmt.Fprintf(w, "Account with number %v can't be found!", number)
} else {
err := account.Deposit(amount)
if err != nil {
fmt.Fprintf(w, "%v", err)
} else {
fmt.Fprintf(w, account.Statement())
}
}
}
}
Zwróć uwagę, że ta funkcja jest zgodna z podobnym podejściem, aby pobrać i zweryfikować dane odbierane od użytkownika. Deklarujemy również zmienne i używamy ich bezpośrednio w instrukcji if
. Na koniec, po dodaniu niektórych środków na konto, drukujemy zestawienie, aby zobaczyć nowe saldo konta.
Teraz należy uwidocznić /deposit
punkt końcowy wywołujący deposit
funkcję. Zmodyfikuj funkcję main()
tak, aby wyglądała następująco:
func main() {
accounts[1001] = &bank.Account{
Customer: bank.Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
}
http.HandleFunc("/statement", statement)
http.HandleFunc("/deposit", deposit)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
Jeśli nie widzisz żadnego błędu lub danych wyjściowych podczas uruchamiania programu (go run main.go
), działa on poprawnie. Otwórz przeglądarkę internetową i wprowadź adres URL http://localhost:8000/deposit?number=1001&amount=100
lub uruchom następujące polecenie w innej powłoce, gdy program jest uruchomiony:
curl "http://localhost:8000/deposit?number=1001&amount=100"
Powinny zostać wyświetlone następujące dane wyjściowe:
1001 - John - 100
Jeśli wykonasz to samo wywołanie kilka razy, saldo konta będzie nadal wzrastać. Spróbuj potwierdzić, że accounts
mapa w pamięci jest aktualizowana w czasie wykonywania. Jeśli zatrzymasz program, wszystkie depozyty, które zrobiłeś, zostaną utracone, ale jest to oczekiwane w tej początkowej wersji.
Uwidacznij metodę wycofywania
Na koniec uwidocznijmy metodę wypłaty pieniędzy z konta. Ponownie utwórzmy withdraw
funkcję w głównym programie. Funkcja zweryfikuje informacje o numerze konta, wycofa i wyświetli wszelkie błędy otrzymane z pakietu podstawowego. Dodaj następującą funkcję do głównego programu:
func withdraw(w http.ResponseWriter, req *http.Request) {
numberqs := req.URL.Query().Get("number")
amountqs := req.URL.Query().Get("amount")
if numberqs == "" {
fmt.Fprintf(w, "Account number is missing!")
return
}
if number, err := strconv.ParseFloat(numberqs, 64); err != nil {
fmt.Fprintf(w, "Invalid account number!")
} else if amount, err := strconv.ParseFloat(amountqs, 64); err != nil {
fmt.Fprintf(w, "Invalid amount number!")
} else {
account, ok := accounts[number]
if !ok {
fmt.Fprintf(w, "Account with number %v can't be found!", number)
} else {
err := account.Withdraw(amount)
if err != nil {
fmt.Fprintf(w, "%v", err)
} else {
fmt.Fprintf(w, account.Statement())
}
}
}
}
Teraz dodaj /withdraw
punkt końcowy w main()
funkcji, aby uwidocznić logikę withdraw()
, która jest dostępna w funkcji. Zmodyfikuj funkcję tak main()
, aby wyglądała następująco:
func main() {
accounts[1001] = &bank.Account{
Customer: bank.Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
}
http.HandleFunc("/statement", statement)
http.HandleFunc("/deposit", deposit)
http.HandleFunc("/withdraw", withdraw)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
Jeśli nie widzisz żadnego błędu lub danych wyjściowych podczas uruchamiania programu (go run main.go
), działa on poprawnie. Otwórz przeglądarkę internetową i wprowadź adres URL http://localhost:8000/withdraw?number=1001&amount=100
lub uruchom następujące polecenie w innej powłoce, gdy program jest uruchomiony:
curl "http://localhost:8000/withdraw?number=1001&amount=100"
Powinny zostać wyświetlone następujące dane wyjściowe:
the amount to withdraw should be greater than the account's balance
Zwróć uwagę, że błąd, który otrzymujemy, pochodzi z podstawowego pakietu. Po uruchomieniu programu saldo konta wynosi zero. W związku z tym nie można wycofać żadnej kwoty pieniędzy. Wywołaj /deposit
punkt końcowy kilka razy, aby dodać fundusze, a następnie ponownie wywołaj /withdraw
punkt końcowy, aby potwierdzić, że działa:
curl "http://localhost:8000/deposit?number=1001&amount=100"
curl "http://localhost:8000/deposit?number=1001&amount=100"
curl "http://localhost:8000/deposit?number=1001&amount=100"
curl "http://localhost:8000/withdraw?number=1001&amount=100"
Powinny zostać wyświetlone następujące dane wyjściowe:
1001 - John - 200
I już! Utworzono internetowy interfejs API umożliwiający uwidacznianie funkcji z pakietu utworzonego od podstaw. Przejdź do następnej sekcji, aby kontynuować ćwiczenia. Tym razem zostanie wyświetlone wyzwanie, w którym napiszesz własne rozwiązanie.