{"id":633,"date":"2020-09-13T17:46:23","date_gmt":"2020-09-13T15:46:23","guid":{"rendered":"http:\/\/www.valeriofinazzo.it\/wordpress\/?p=633"},"modified":"2020-10-30T17:39:52","modified_gmt":"2020-10-30T16:39:52","slug":"tutorial-go-implementare-dei-servizi-http","status":"publish","type":"post","link":"http:\/\/www.valeriofinazzo.it\/wordpress\/2020\/09\/tutorial-go-implementare-dei-servizi-http\/","title":{"rendered":"TUTORIAL GO &#8211; IMPLEMENTARE DEI SERVIZI HTTP"},"content":{"rendered":"\n<p>Nell&#8217;articolo di oggi vedremo come instanziare un server ed esporre dei servizi per lettura e scrittura di una entit\u00e0. Per fare questo utilizzeremo 2 nuovi package &#8220;net\/http&#8221; e &#8220;encoding\/json&#8221;, il primo ci permette di instanziare il server e definire le azioni da intraprendere per dei path, il secondo ci consente agevolvemente di fare encoding e decoding di oggetti json.<\/p>\n\n\n\n<p>Incominciamo instanziando il server e implementando un servizio di keepalive che serve a stabilire se il server \u00e8 attivo regolarmente.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\thttp.HandleFunc(\"\/isAlive\", isAlive)\n\tlog.Fatal(http.ListenAndServe(\":10000\", nil))<\/pre>\n\n\n\n<p>La funzione HandleFunc definisce il path e il relativo handler. Per handler si intende la funzione che verr\u00e0 eseguita dal server in corrispondenza della richiesta riceveuta.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">func isAlive(response http.ResponseWriter, request *http.Request) {\n\tfmt.Fprintf(response, \"alive\")\n}<\/pre>\n\n\n\n<p>Se abbiamo fatto tutto bene invocando il servizio http:\/\/localhost:10000\/isAlive riceveremo un 200 ok con testo alive.<\/p>\n\n\n\n<p>A questo punto supponiamo di voler gestire una rubrica dei contatti e pertanto definiamo prima di tutto la nostra struct Contatto<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">type contatto struct {\n\tNome    string `json:\"Nome\"`\n\tCognome string `json:\"Cognome\"`\n}<\/pre>\n\n\n\n<p>La struct presenta 2 parametri Nome e Cognome e relative regole di trascodifica in json. Definiamo l&#8217;elenco dei contatti e lo inizializziamo con dei dati di prova, simulando la presenza di un database<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">var contatti []contatto\nfunc main() {\n\n\tcontatti = []contatto{\n\t\tcontatto{Nome: \"nome 1\", Cognome: \"Cognome 1\"},\n\t\tcontatto{Nome: \"nome 2\", Cognome: \"Cognome 2\"},\n\t}<\/pre>\n\n\n\n<p>Infine definiamo l&#8217;handler relativo<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">func elencoContatti(response http.ResponseWriter, request *http.Request) {\n\tjson.NewEncoder(response).Encode(contatti)\n}\n\nfunc main() {\n        http.HandleFunc(\"\/contatti\", elencoContatti)\n}<\/pre>\n\n\n\n<p>In tal modo invocando l&#8217;url http:\/\/localhost:10000\/contatti otterremo il seguente json [{&#8220;Nome&#8221;:&#8221;nome 1&#8243;,&#8221;Cognome&#8221;:&#8221;Cognome 1&#8243;},{&#8220;Nome&#8221;:&#8221;nome 2&#8243;,&#8221;Cognome&#8221;:&#8221;Cognome 2&#8243;}]<\/p>\n\n\n\n<p>Di seguito il codice completo <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">package main\n\nimport (\n\t\"encoding\/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\/http\"\n)\n\ntype contatto struct {\n\tNome    string `json:\"Nome\"`\n\tCognome string `json:\"Cognome\"`\n}\n\nfunc isAlive(response http.ResponseWriter, request *http.Request) {\n\tfmt.Fprintf(response, \"alive\")\n}\n\nfunc elencoContatti(response http.ResponseWriter, request *http.Request) {\n\tjson.NewEncoder(response).Encode(contatti)\n}\n\nvar contatti []contatto\n\nfunc main() {\n\n\tcontatti = []contatto{\n\t\tcontatto{Nome: \"nome 1\", Cognome: \"Cognome 1\"},\n\t\tcontatto{Nome: \"nome 2\", Cognome: \"Cognome 2\"},\n\t}\n\n\tfmt.Println(\"Http server up \")\n\thttp.HandleFunc(\"\/isAlive\", isAlive)\n\thttp.HandleFunc(\"\/contatti\", elencoContatti)\n\n\tlog.Fatal(http.ListenAndServe(\":10000\", nil))\n}<\/pre>\n\n\n\n<p>Il package http ci ha consentito di tirare su il server e configurare delle risposte su dei path statici. Il package ha dei limiti, non ci permette di configurare degli endpoint variabili ed esplicitare il metodo http supportato. Per superare questo limite ci viene in soccorso un nuovo package   &#8220;github.com\/gorilla\/mux&#8221;. Il package va installato con il comando <\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">go get -u github.com\/gorilla\/mux<\/pre>\n\n\n\n<p>A questo per tirare su il server e configurare opportunamente gli endpoint possiamo scrivere<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\tmyRouter := mux.NewRouter().StrictSlash(true)\n\tmyRouter.HandleFunc(\"\/isAlive\", isAlive).Methods(\"GET\")\n\tmyRouter.HandleFunc(\"\/contatti\", elencoContatti).Methods(\"GET\")\n\tmyRouter.HandleFunc(\"\/contatti\/{id}\", singoloContatto).Methods(\"GET\")\n\tmyRouter.HandleFunc(\"\/contatti\", creaContatto).Methods(\"POST\")\n\tmyRouter.HandleFunc(\"\/contatti\/{id}\", eliminaContatto).Methods(\"DELETE\")\n\tlog.Fatal(http.ListenAndServe(\":10000\", myRouter))<\/pre>\n\n\n\n<p>Il packge ci mette a disposizione l&#8217;oggetto router che consente per ogni  handler di definire maggiori propriet\u00e0 per meglio mappare il comportamento<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">func singoloContatto(response http.ResponseWriter, request *http.Request) {\n\tvars := mux.Vars(request)\n\tkey := vars[\"id\"]\n\tfor index, contatto := range contatti {\n\t\tfmt.Println(index, \" \", key)\n\t\ti, _ := strconv.Atoi(key)\n\t\tif index == i {\n\t\t\tjson.NewEncoder(response).Encode(contatto)\n\t\t\treturn\n\t\t}\n\t}\n\tresponse.WriteHeader(http.StatusNotFound)\n}<\/pre>\n\n\n\n<p>Il package ci consente agevolmente di leggere le path variable e superare i limiti del package net\/http.<\/p>\n\n\n\n<p>Di seguito il codice completo per l&#8217;analisi dei metodi restanti<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">package main\n\nimport (\n\t\"encoding\/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\/http\"\n\t\"strconv\"\n\n\t\"github.com\/gorilla\/mux\"\n)\n\ntype contatto struct {\n\tNome    string `json:\"Nome\"`\n\tCognome string `json:\"Cognome\"`\n}\n\nfunc isAlive(response http.ResponseWriter, request *http.Request) {\n\tfmt.Fprintf(response, \"alive\")\n}\n\nfunc elencoContatti(response http.ResponseWriter, request *http.Request) {\n\tjson.NewEncoder(response).Encode(contatti)\n}\n\nfunc creaContatto(response http.ResponseWriter, request *http.Request) {\n\tvar contatto contatto\n\tjson.NewDecoder(request.Body).Decode(&amp;contatto)\n\tcontatti = append(contatti, contatto)\n\tjson.NewEncoder(response).Encode(contatti)\n}\n\nfunc singoloContatto(response http.ResponseWriter, request *http.Request) {\n\tvars := mux.Vars(request)\n\tkey := vars[\"id\"]\n\tfor index, contatto := range contatti {\n\t\tfmt.Println(index, \" \", key)\n\t\ti, _ := strconv.Atoi(key)\n\t\tif index == i {\n\t\t\tjson.NewEncoder(response).Encode(contatto)\n\t\t\treturn\n\t\t}\n\t}\n\tresponse.WriteHeader(http.StatusNotFound)\n}\n\nfunc eliminaContatto(response http.ResponseWriter, request *http.Request) {\n\tvars := mux.Vars(request)\n\tkey := vars[\"id\"]\n\tfor index := range contatti {\n\t\tfmt.Println(index, \" \", key)\n\t\ti, _ := strconv.Atoi(key)\n\t\tif index == i {\n\t\t\tcontatti = append(contatti[:index], contatti[index+1:]...)\n\t\t\tresponse.WriteHeader(http.StatusOK)\n\t\t\treturn\n\t\t}\n\t}\n\tresponse.WriteHeader(http.StatusNotFound)\n}\n\nvar contatti []contatto\n\nfunc main() {\n\n\tcontatti = []contatto{\n\t\tcontatto{Nome: \"nome 1\", Cognome: \"Cognome 1\"},\n\t\tcontatto{Nome: \"nome 2\", Cognome: \"Cognome 2\"},\n\t}\n\n\tfmt.Println(\"Http server up \")\n\t\/\/http.HandleFunc(\"\/isAlive\", isAlive)\n\t\/\/http.HandleFunc(\"\/contatti\", elencoContatti)\n\n\tmyRouter := mux.NewRouter().StrictSlash(true)\n\tmyRouter.HandleFunc(\"\/isAlive\", isAlive).Methods(\"GET\")\n\tmyRouter.HandleFunc(\"\/contatti\", elencoContatti).Methods(\"GET\")\n\tmyRouter.HandleFunc(\"\/contatti\/{id}\", singoloContatto).Methods(\"GET\")\n\tmyRouter.HandleFunc(\"\/contatti\", creaContatto).Methods(\"POST\")\n\tmyRouter.HandleFunc(\"\/contatti\/{id}\", eliminaContatto).Methods(\"DELETE\")\n\tlog.Fatal(http.ListenAndServe(\":10000\", myRouter))\n}\n<\/pre>\n\n\n\n<p>Alla prossima<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nell&#8217;articolo di oggi vedremo come instanziare un server ed esporre dei servizi per lettura e scrittura di una entit\u00e0. Per fare questo utilizzeremo 2 nuovi package &#8220;net\/http&#8221; e &#8220;encoding\/json&#8221;, il primo ci permette di instanziare il server e definire le azioni da intraprendere per dei path, il secondo ci consente agevolvemente di fare encoding e &hellip; <a href=\"http:\/\/www.valeriofinazzo.it\/wordpress\/2020\/09\/tutorial-go-implementare-dei-servizi-http\/\" class=\"more-link\">Continua la lettura di <span class=\"screen-reader-text\">TUTORIAL GO &#8211; IMPLEMENTARE DEI SERVIZI HTTP<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[148],"tags":[136,132,137],"_links":{"self":[{"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/posts\/633"}],"collection":[{"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/comments?post=633"}],"version-history":[{"count":2,"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/posts\/633\/revisions"}],"predecessor-version":[{"id":635,"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/posts\/633\/revisions\/635"}],"wp:attachment":[{"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/media?parent=633"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/categories?post=633"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.valeriofinazzo.it\/wordpress\/wp-json\/wp\/v2\/tags?post=633"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}