Tải bản đầy đủ (.pdf) (39 trang)

Building WEB APPS with GO

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.16 MB, 39 trang )


BuildingWebAppswithGo

TableofContents
Introduction

0

GoMakesThingsSimple

1

Thenet/httppackage

2

CreatingaBasicWebApp

3

Deployment

4

URLRouting

5

Middleware

6



Rendering

7

JSON

7.1

HTMLTemplates

7.2

UsingTherenderpackage

7.3

Testing

8

UnitTesting

8.1

EndtoEndTesting

8.2

Controllers


9

Databases

10

TipsandTricks

11

MovingForward

12

2


BuildingWebAppswithGo

Introduction
WelcometoBuildingWebAppswithGo!Ifyouarereadingthisthenyouhavejuststarted
yourjourneyfromnoobtopro.Noseriously,webprogramminginGoissofunandeasythat
youwon'tevennoticehowmuchinformationyouarelearningalongtheway!
Keepinmindthattherearestillportionsofthisbookthatareincompleteandneedsome
love.ThebeautyofopensourcepublishingisthatIcangiveyouanincompletebookandit
isstillofvaluetoyou.
Beforewegetintoallthenittygrittydetails,let'sstartwithsomegroundrules:

Prerequisites

Tokeepthistutorialsmallandfocused,I'massumingthatyouarepreparedinthefollowing
ways:
1. YouhaveinstalledtheGoProgrammingLanguage.
2. Youhavesetupa GOPATHbyfollowingtheHowtoWriteGoCodetutorial.
3. YouaresomewhatfamiliarwiththebasicsofGo.(TheGoTourisaprettygoodplaceto
start)
4. Youhaveinstalledalltherequiredpackages
5. YouhaveinstalledtheHerokuToolbelt
6. YouhaveaHerokuaccount

RequiredPackages
Forthemostpartwewillbeusingthebuiltinpackagesfromthestandardlibrarytobuildout
ourwebapps.CertainlessonssuchasDatabases,MiddlewareandURLRoutingwillrequire
athirdpartypackage.Hereisalistofallthegopackagesyouwillneedtoinstallbefore
starting:

Introduction

3


BuildingWebAppswithGo

Name

ImportPath

Description

httprouter


github.com/julienschmidt/httprouter

AhighperformanceHTTPrequest
routerthatscaleswell

Negroni

github.com/codegangsta/negroni

IdiomaticHTTPMiddleware

Black
Friday

github.com/russross/blackfriday

amarkdownprocessor

Render

gopkg.in/unrolled/render.v1

EasyrenderingforJSON,XML,and
HTML

SQLite3

github.com/mattn/go-sqlite3


sqlite3driverforgo

Youcaninstall(orupdate)thesepackagesbyrunningthefollowingcommandinyour
console
goget-u<import_path>

Forinstance,ifyouwishtoinstallNegroni,thefollowingcommandwouldbe:
goget-ugithub.com/codegangsta/negroni

Introduction

4


BuildingWebAppswithGo

GoMakesThingsSimple
Ifyouhavebuiltawebapplicationbefore,yousurelyknowthattherearequitealotof
conceptstokeepinyourhead.HTTP,HTML,CSS,JSON,databases,sessions,cookies,
forms,middleware,routingandcontrollersarejustafewamongthemanythingsyourweb
appmayneedtointeractwith.
Whileeachoneofthesethingscanbeimportantinthebuildingofyourwebapplications,not
everyoneofthemisimportantforanygivenapp.Forinstance,awebAPImayjustuse
JSONasitsserializationformat,thusmakingconceptslikeHTMLnotrelevantforthat
particularwebapp.

TheGoWay
TheGocommunityunderstandsthisdilemma.Ratherthanrelyonlarge,heavyweight
frameworksthattrytocoverallthebases,Goprogrammerspullinthebarenecessitiesto
getthejobdone.Thisminimalistapproachtowebprogrammingmaybeoff-puttingatfirst,

buttheresultofthiseffortisamuchsimplerprogramintheend.
Gomakesthingssimple,it'saseasyasthat.Ifwetrainourselvestoalignwiththe"Go
way"ofprogrammingfortheweb,wewillendupwithmoresimple,flexible,and
maintainablewebapplications.

PowerinSimplicity
Aswegothroughtheexercisesinthisbook,Ithinkyouwillbesurprisedbyhowsimple
someoftheseprogramscanbewhilststillaffordingabunchoffunctionality.
WhensittingdowntocraftyourownwebapplicationsinGo,thinkhardaboutthe
componentsandconceptsthatyourappwillbefocusedon,andusejustthosepieces.This
bookwillbecoveringawidearrayofwebtopics,butdonotfeelobligatedtousethemall.In
thewordsofourfriendLonestar,"Takeonlywhatyouneedtosurvive".

GoMakesThingsSimple

5


BuildingWebAppswithGo

GoMakesThingsSimple

6


BuildingWebAppswithGo

Thenet/httpPackage
YouhaveprobablyheardthatGoisfantasticforbuildingwebapplicationsofallshapesand
sizes.Thisispartlyduetothefantasticworkthathasbeenputintomakingthestandard

libraryclean,consistent,andeasytouse.
PerhapsoneofthemostimportantpackagesforanybuddingGowebdeveloperisthe
net/httppackage.ThispackageallowsyoutobuildHTTPserversinGowithitspowerful

compositionalconstructs.Beforewestartcoding,let'sdoanextremelyquickoverviewof
HTTP.

HTTPBasics
Whenwetalkaboutbuildingwebapplications,weusuallymeanthatwearebuildingHTTP
servers.HTTPisaprotocolthatwasoriginallydesignedtotransportHTMLdocumentsfrom
aservertoaclientwebbrowser.Today,HTTPisusedtotransportawholelotmorethan
HTML.

Theimportantthingtonoticeinthisdiagramisthetwopointsofinteractionbetweenthe
ServerandtheBrowser.TheBrowsermakesanHTTPrequestwithsomeinformation,the
ServerthenprocessesthatrequestandreturnsaResponse.

Thenet/httppackage

7


BuildingWebAppswithGo

Thispatternofrequest-responseisoneofthekeyfocalpointsinbuildingwebapplicationsin
Go.Infact,the net/httppackage'smostimportantpieceisthe http.HandlerInterface.

Thehttp.HandlerInterface
AsyoubecomemorefamiliarwithGo,youwillnoticehowmuchofanimpactinterfaces
makeinthedesignofyourprograms.The net/httpinterfaceencapsulatestherequestresponsepatterninonemethod:

typeHandlerinterface{
ServeHTTP(ResponseWriter,*Request)
}

Implementorsofthisinterfaceareexpectedtoinspectandprocessdatacomingfromthe
http.Requestobjectandwriteoutaresponsetothe http.ResponseWriterobject.

The http.ResponseWriterinterfacelookslikethis:
typeResponseWriterinterface{
Header()Header
Write([]byte)(int,error)
WriteHeader(int)
}

ComposingWebServices
Becausemuchofthe net/httppackageisbuiltoffofwelldefinedinterfacetypes,wecan
(andareexpectedto)buildourwebapplicationswithcompositioninmind.Each
http.Handlerimplementationcanbethoughtofasitsownwebserver.

Manypatternscanbefoundinthatsimplebutpowerfulassumption.Throughoutthisbook
wewillcoversomeofthesepatternsandhowwecanusethemtosolverealworld
problems.

Exercise:1LineFileServer
Let'ssolvearealworldproblemin1lineofcode.

Thenet/httppackage

8



BuildingWebAppswithGo

Mostofthetimepeoplejustneedtoservestaticfiles.MaybeyouhaveastaticHTML
landingpageandjustwanttoserveupsomeHTML,images,andCSSandcallitaday.
Sure,youcouldpullinApacheorPython's SimpleHTTPServer,butApacheistoomuchfor
thislittlesiteand SimpleHTTPServeris,well,tooslow.
Wewillbeginbycreatinganewprojectinour GOPATH.
cdGOPATH/src
mkdirfileserver&&cdfileserver

Createamain.gowithourtypicalgoboilerplate.
packagemain
import"net/http"
funcmain(){
}

Allweneedtoimportisthe net/httppackageforthistowork.Rememberthatthisisall
partofthestandardlibraryinGo.
Let'swriteourfileservercode:
http.ListenAndServe(":8080",http.FileServer(http.Dir(".")))

The http.ListenAndServefunctionisusedtostarttheserver,itwillbindtotheaddresswe
gaveit( :8080)andwhenitreceivesanHTTPrequest,itwillhanditofftothe
http.Handlerthatwesupplyasthesecondargument.Inourcaseitisthebuilt-in
http.FileServer.

The http.FileServerfunctionbuildsan http.Handlerthatwillserveanentiredirectoryof
filesandfigureoutwhichfiletoservebasedontherequestpath.WetoldtheFileServerto
servethecurrentworkingdirectorywith http.Dir(".").

Theentireprogramlookslikethis:
packagemain
import"net/http"
funcmain(){
http.ListenAndServe(":8080",http.FileServer(http.Dir(".")))
}

Thenet/httppackage

9


BuildingWebAppswithGo

Let'sbuildandrunourfileserverprogram:
gobuild
./fileserver

Ifwevisit localhost:8080/main.goweshouldseethecontentsofourmain.gofileinourweb
browser.Wecanrunthisprogramfromanydirectoryandservethetreeasastaticfile
server.Allin1lineofGocode.

Thenet/httppackage

10


BuildingWebAppswithGo

CreatingaBasicWebApp

NowthatwearedonegoingoverthebasicsofHTTP,let'screateasimplebutusefulweb
applicationinGo.
Pullingfromourfileserverprogramthatweimplementedlastchapter,wewillimplementa
Markdowngeneratorusingthe github.com/russross/blackfridaypackage.

HTMLForm
Forstarters,wewillneedabasicHTMLformforthemarkdowninput:
<html>
<head>
<linkhref="/css/bootstrap.min.css"rel="stylesheet">
</head>
<body>
<divclass="container">
<divclass="page-title">

MarkdownGenerator


GenerateyourmarkdownwithGo


<hr/>
</div>
<formaction="/markdown"method="POST">
<divclass="form-group">
<textareaclass="form-control"name="body"cols="30"rows="10"></textarea>
</div>
<divclass="form-group">
<inputtype="submit"class="btnbtn-primarypull-right"/>
</div>
</form>
</div>
<scriptsrc="/js/bootstrap.min.js"></script>
</body>
</html>


PutthisHTMLintoafilenamed index.htmlinthe"public"folderofourapplicationandthe
bootstrap.min.cssfrominthe"public/css"folder.Noticethatthe

formmakesanHTTPPOSTtothe"/markdown"endpointofourapplication.Wedon't
actuallyhandlethatrouterightnow,solet'saddit.

CreatingaBasicWebApp

11


BuildingWebAppswithGo

The"/markdown"route
Theprogramtohandlethe'/markdown'routeandservethepublic index.htmlfilelookslike
this:
packagemain
import(
"net/http"
"github.com/russross/blackfriday"
)
funcmain(){
http.HandleFunc("/markdown",GenerateMarkdown)
http.Handle("/",http.FileServer(http.Dir("public")))
http.ListenAndServe(":8080",nil)
}
funcGenerateMarkdown(rwhttp.ResponseWriter,r*http.Request){
markdown:=blackfriday.MarkdownCommon([]byte(r.FormValue("body")))
rw.Write(markdown)

}

Let'sbreakitdownintosmallerpiecestogetabetterideaofwhatisgoingon.
http.HandleFunc("/markdown",GenerateMarkdown)
http.Handle("/",http.FileServer(http.Dir("public")))

Weareusingthe http.HandleFuncand http.Handlemethodstodefinesomesimple
routingforourapplication.Itisimportanttonotethatcalling http.Handleonthe"/"pattern
willactasacatch-allroute,sowedefinethatroutelast. http.FileServerreturnsan
http.Handlersoweuse http.Handletomapapatternstringtoahandler.Thealternative

method, http.HandleFunc,usesan http.HandlerFuncinsteadofan http.Handler.This
maybemoreconvenient,tothinkofhandlingroutesviaafunctioninsteadofanobject.
funcGenerateMarkdown(rwhttp.ResponseWriter,r*http.Request){
markdown:=blackfriday.MarkdownCommon([]byte(r.FormValue("body")))
rw.Write(markdown)
}

OurGenerateMarkdownfunctionimplementsthestandard http.HandlerFuncinterfaceand
rendersHTMLfromaformfieldcontainingmarkdown-formattedtext.Inthiscase,the
contentisretrievedwith r.FormValue("body").Itisverycommontogetinputfromthe

CreatingaBasicWebApp

12


BuildingWebAppswithGo

http.Requestobjectthatthe http.HandlerFuncreceivesasanargument.Someother


examplesofinputarethe r.Header, r.Body,and r.URLmembers.
Wefinalizetherequestbywritingitouttoour http.ResponseWriter.Noticethatwedidn't
explicitlysendaresponsecode.Ifwewriteouttotheresponsewithoutacode,the
net/httppackagewillassumethattheresponseisa 200OK.Thismeansthatif

somethingdidhappentogowrong,weshouldsettheresponsecodeviathe
rw.WriteHeader()method.

http.ListenAndServe(":8080",nil)

Thelastbitofthisprogramstartstheserver,wepass nilasourhandler,whichassumes
thattheHTTPrequestswillbehandledbythe net/httppackagesdefault http.ServeMux,
whichisconfiguredusing http.Handleand http.HandleFunc,respectively.
AndthatisallyouneedtobeabletogeneratemarkdownasaserviceinGo.Itisa
surprisinglysmallamountofcodefortheamountofheavyliftingitdoes.Inthenextchapter
wewilllearnhowtodeploythisapplicationtothewebusingHeroku.

CreatingaBasicWebApp

13


BuildingWebAppswithGo

Deployment
Herokumakesdeployingapplicationseasy.Itisaperfectplatformforsmalltomediumsize
webapplicationsthatarewillingtosacrificealittlebitofflexibilityininfrastructuretogaina
fairlypain-freeenvironmentfordeployingandmaintainingwebapplications.
IamchoosingtodeployourwebapplicationtoHerokuforthesakeofthistutorialbecausein

myexperienceithasbeenthefastestwaytogetawebapplicationupandrunninginno
time.RememberthatthefocusofthistutorialishowtobuildwebapplicationsinGoandnot
gettingcaughtupinallofthedistractionofprovisioning,configuring,deploying,and
maintainingthemachinesthatourGocodewillberunon.

Gettingsetup
Ifyoudon'talreadyhaveaHerokuaccount,signupatid.heroku.com/signup.It'squick,easy
andfree.
ApplicationmanagementandconfigurationisdonethroughtheHerokutoolbelt,whichisa
freecommandlinetoolmaintainedbyHeroku.Wewillbeusingittocreateourapplication
onHeroku.Youcangetitfromtoolbelt.heroku.com.

ChangingtheCode
TomakesuretheapplicationfromourlastchapterwillworkonHeroku,wewillneedtomake
afewchanges.Herokugivesusa PORTenvironmentvariableandexpectsourweb
applicationtobindtoit.Let'sstartbyimportingthe"os"packagesowecangrabthat PORT
environmentvariable:
import(
"net/http"
"os"
"github.com/russross/blackfriday"
)

Next,weneedtograbthe PORTenvironmentvariable,checkifitisset,andifitisweshould
bindtothatinsteadofourhardcodedport(8080).

Deployment

14



BuildingWebAppswithGo

port:=os.Getenv("PORT")
ifport==""{
port="8080"
}

Lastly,wewanttobindtothatportinour http.ListenAndServecall:
http.ListenAndServe(":"+port,nil)

Thefinalcodeshouldlooklikethis:
packagemain
import(
"net/http"
"os"
"github.com/russross/blackfriday"
)
funcmain(){
port:=os.Getenv("PORT")
ifport==""{
port="8080"
}
http.HandleFunc("/markdown",GenerateMarkdown)
http.Handle("/",http.FileServer(http.Dir("public")))
http.ListenAndServe(":"+port,nil)
}
funcGenerateMarkdown(rwhttp.ResponseWriter,r*http.Request){
markdown:=blackfriday.MarkdownCommon([]byte(r.FormValue("body")))
rw.Write(markdown)

}

Configuration
WeneedacouplesmallconfigurationfilestotellHerokuhowitshouldrunourapplication.
Thefirstoneisthe Procfile,whichallowsustodefinewhichprocessesshouldberunfor
ourapplication.Bydefault,Gowillnametheexecutableafterthecontainingdirectoryofyour
mainpackage.Forinstance,ifmywebapplicationlivedin
GOPATH/github.com/codegangsta/bwag/deployment,my Procfilewilllooklikethis:

Deployment

15


BuildingWebAppswithGo

web:deployment

SpecificallytorunGoapplications,weneedtoalsospecifya .godirfiletotellHeroku
whichdirisinfactourpackagedirectory.
deployment

Deployment
Onceallthesethingsinplace,Herokumakesiteasytodeploy.
InitializetheprojectasaGitrepository:
gitinit
gitadd-A
gitcommit-m"InitialCommit"

CreateyourHerokuapplication(specifyingtheGobuildpack):

herokucreate-b />
PushittoHerokuandwatchyourapplicationbedeployed!
gitpushherokumaster

Viewyourapplicationinyourbrowser:
herokuopen

Deployment

16


BuildingWebAppswithGo

URLRouting
Forsomesimpleapplications,thedefault http.ServeMuxcantakeyouprettyfar.Ifyouneed
morepowerinhowyouparseURLendpointsandroutethemtotheproperhandler,youmay
needtopullinathirdpartyroutingframework.Forthistutorial,wewillusethepopular
github.com/julienschmidt/httprouterlibraryasourrouter.
github.com/julienschmidt/httprouterisagreatchoiceforarouterasitisaverysimple

implementationwithoneofthebestperformancebenchmarksoutofallthethirdpartyGo
routers.
Inthisexample,wewillcreatesomeroutingforaRESTfulresourcecalled"posts".Belowwe
definemechanismstoviewindex,show,create,update,destroy,andeditposts.
packagemain
import(
"fmt"
"net/http"
"github.com/julienschmidt/httprouter"

)
funcmain(){
r:=httprouter.New()
r.GET("/",HomeHandler)
//Postscollection
r.GET("/posts",PostsIndexHandler)
r.POST("/posts",PostsCreateHandler)
//Postssingular
r.GET("/posts/:id",PostShowHandler)
r.PUT("/posts/:id",PostUpdateHandler)
r.GET("/posts/:id/edit",PostEditHandler)
fmt.Println("Startingserveron:8080")
http.ListenAndServe(":8080",r)
}
funcHomeHandler(rwhttp.ResponseWriter,r*http.Request,phttprouter.Params){
fmt.Fprintln(rw,"Home")
}
funcPostsIndexHandler(rwhttp.ResponseWriter,r*http.Request,phttprouter.Params){
fmt.Fprintln(rw,"postsindex")
}

URLRouting

17


BuildingWebAppswithGo

funcPostsCreateHandler(rwhttp.ResponseWriter,r*http.Request,phttprouter.Params){
fmt.Fprintln(rw,"postscreate")

}
funcPostShowHandler(rwhttp.ResponseWriter,r*http.Request,phttprouter.Params){
id:=p.ByName("id")
fmt.Fprintln(rw,"showingpost",id)
}
funcPostUpdateHandler(rwhttp.ResponseWriter,r*http.Request,phttprouter.Params){
fmt.Fprintln(rw,"postupdate")
}
funcPostDeleteHandler(rwhttp.ResponseWriter,r*http.Request,phttprouter.Params){
fmt.Fprintln(rw,"postdelete")
}
funcPostEditHandler(rwhttp.ResponseWriter,r*http.Request,phttprouter.Params){
fmt.Fprintln(rw,"postedit")
}

Exercises
1. Explorethedocumentationfor github.com/julienschmidt/httprouter.
2. Findouthowwell github.com/julienschmidt/httprouterplaysnicelywithexisting
http.Handlerslike http.FileServer

3.

httprouterhasaverysimpleinterface.Explorewhatkindofabstractionscanbebuilt

ontopofthisfastroutertomakebuildingthingslikeRESTfulroutingeasier.

URLRouting

18



BuildingWebAppswithGo

Middleware
Ifyouhavesomecodethatneedstoberunforeveryrequest,regardlessoftheroutethatit
willeventuallyendupinvoking,youneedsomewaytostack http.Handlersontopofeach
otherandruntheminsequence.Thisproblemissolvedelegantlythroughmiddleware
packages.Negroniisapopularmiddlewarepackagethatmakesbuildingandstacking
middlewareveryeasywhilekeepingthecomposablenatureoftheGowebecosystemintact.
NegronicomeswithsomedefaultmiddlewaresuchasLogging,ErrorRecovery,andStatic
fileserving.SooutoftheboxNegroniwillprovideyouwithalotofvaluewithoutalotof
overhead.
TheexamplebelowshowshowtouseaNegronistackwiththebuiltinmiddlewareandhow
tocreateyourowncustommiddleware.

Middleware

19


BuildingWebAppswithGo

packagemain
import(
"log"
"net/http"
"github.com/codegangsta/negroni"
)
funcmain(){
//Middlewarestack

n:=negroni.New(
negroni.NewRecovery(),
negroni.HandlerFunc(MyMiddleware),
negroni.NewLogger(),
negroni.NewStatic(http.Dir("public")),
)
n.Run(":8080")
}
funcMyMiddleware(rwhttp.ResponseWriter,r*http.Request,nexthttp.HandlerFunc){
log.Println("Loggingonthewaythere...")
ifr.URL.Query().Get("password")=="secret123"{
next(rw,r)
}else{
http.Error(rw,"NotAuthorized",401)
}
log.Println("Loggingonthewayback...")
}

Exercises
1. ThinkofsomecoolmiddlewareideasandtrytoimplementthemusingNegroni.
2. ExplorehowNegronicanbecomposedwith github.com/gorilla/muxusingthe
http.Handlerinterface.

3. PlaywithcreatingNegronistacksforcertaingroupsofroutesinsteadoftheentire
application.

Middleware

20



BuildingWebAppswithGo

Rendering
Renderingistheprocessoftakingdatafromyourapplicationordatabaseandpresentingit
fortheclient.TheclientcanbeabrowserthatrendersHTML,oritcanbeanother
applicationthatconsumesJSONasitsserializationformat.Inthischapterwewilllearnhow
torenderbothoftheseformatsusingthemethodsthatGoprovidesforusinthestandard
library.

Rendering

21


BuildingWebAppswithGo

JSON
JSONisquicklybecomingtheubiquitousserializationformatforwebAPIs,soitmaybethe
mostrelevantwhenlearninghowtobuildwebappsusingGo.Fortunately,Gomakesit
simpletoworkwithJSON--itisextremelyeasytoturnexistingGostructsintoJSONusing
the encoding/jsonpackagefromthestandardlibrary.
packagemain
import(
"encoding/json"
"net/http"
)
typeBookstruct{
Titlestring`json:"title"`
Authorstring`json:"author"`

}
funcmain(){
http.HandleFunc("/",ShowBooks)
http.ListenAndServe(":8080",nil)
}
funcShowBooks(whttp.ResponseWriter,r*http.Request){
book:=Book{"BuildingWebAppswithGo","JeremySaenz"}
js,err:=json.Marshal(book)
iferr!=nil{
http.Error(w,err.Error(),http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type","application/json")
w.Write(js)
}

Exercises
1. ReadthroughtheJSONAPIdocsandfindouthowtorenameandignorefieldsfor
JSONserialization.
2. Insteadofusingthe json.Marshalmethod,tryusingthe json.EncoderAPI.
3. FigureourhowtoprettyprintJSONwiththe encoding/jsonpackage.

JSON

22


BuildingWebAppswithGo

HTMLTemplates

ServingHTMLisanimportantjobforsomewebapplications.Gohasoneofmyfavorite
templatinglanguagestodate.Notforitsfeatures,butforitssimplicityandoutofthebox
security.RenderingHTMLtemplatesisalmostaseasyasrenderingJSONusingthe
'html/template'packagefromthestandardlibrary.Hereiswhatthesourcecodeforrendering
HTMLtemplateslookslike:
packagemain
import(
"html/template"
"net/http"
"path"
)
typeBookstruct{
Titlestring
Authorstring
}
funcmain(){
http.HandleFunc("/",ShowBooks)
http.ListenAndServe(":8080",nil)
}
funcShowBooks(whttp.ResponseWriter,r*http.Request){
book:=Book{"BuildingWebAppswithGo","JeremySaenz"}
fp:=path.Join("templates","index.html")
tmpl,err:=template.ParseFiles(fp)
iferr!=nil{
http.Error(w,err.Error(),http.StatusInternalServerError)
return
}
iferr:=tmpl.Execute(w,book);err!=nil{
http.Error(w,err.Error(),http.StatusInternalServerError)
}

}

Thisisthefollowingtemplatewewillbeusing.Itshouldbeplacedina
templates/index.htmlfileinthedirectoryyourprogramisrunfrom:

HTMLTemplates

23


BuildingWebAppswithGo

<html>

{{.Title}}


by{{.Author}}


</html>

Exercises
1. Lookthroughthedocsfor text/templateand html/templatepackage.Playwiththe
templatinglanguageabittogetafeelforitsgoals,strengths,andweaknesses.
2. Intheexampleweparsethefilesoneveryrequest,whichcanbealotofperformance
overhead.Experimentwithparsingthefilesatthebeginningofyourprogramand
executingtheminyour http.Handler(hint:makeuseofthe Copy()methodon
html.Template).

3. Experimentwithparsingandusingmultipletemplates.

HTMLTemplates

24



BuildingWebAppswithGo

Usingtherenderpackage
IfyouwantrenderingJSONandHTMLtobeevensimpler,thereisthe
github.com/unrolled/renderpackage.Thispackagewasinspiredbythe martinicontrib/renderpackageandismygotowhenitcomestorenderingdataforpresentationin

mywebapplications.
packagemain
import(
"net/http"
"gopkg.in/unrolled/render.v1"
)
funcmain(){
r:=render.New(render.Options{})
mux:=http.NewServeMux()
mux.HandleFunc("/",func(whttp.ResponseWriter,req*http.Request){
w.Write([]byte("Welcome,visitsubpagesnow."))
})
mux.HandleFunc("/data",func(whttp.ResponseWriter,req*http.Request){
r.Data(w,http.StatusOK,[]byte("Somebinarydatahere."))
})
mux.HandleFunc("/json",func(whttp.ResponseWriter,req*http.Request){
r.JSON(w,http.StatusOK,map[string]string{"hello":"json"})
})
mux.HandleFunc("/html",func(whttp.ResponseWriter,req*http.Request){
//Assumesyouhaveatemplatein./templatescalled"example.tmpl"
//$mkdir-ptemplates&&echo"

Hello{{.}}.

">templates/example.tmpl
r.HTML(w,http.StatusOK,"example",nil)

})
http.ListenAndServe(":8080",mux)
}

Exercises
1. Havefunplayingwithalloftheoptionsavailablewhencalling render.New()
2. Tryusingthe .yieldhelperfunction(withthecurlybraces)andalayoutwithHTML

UsingTherenderpackage

25


Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×