學(xué)習(xí)筆記從2012年初開(kāi)始和研究Go語(yǔ)言雖不敢說(shuō)精通但總體上還是_第1頁(yè)
學(xué)習(xí)筆記從2012年初開(kāi)始和研究Go語(yǔ)言雖不敢說(shuō)精通但總體上還是_第2頁(yè)
學(xué)習(xí)筆記從2012年初開(kāi)始和研究Go語(yǔ)言雖不敢說(shuō)精通但總體上還是_第3頁(yè)
學(xué)習(xí)筆記從2012年初開(kāi)始和研究Go語(yǔ)言雖不敢說(shuō)精通但總體上還是_第4頁(yè)
學(xué)習(xí)筆記從2012年初開(kāi)始和研究Go語(yǔ)言雖不敢說(shuō)精通但總體上還是_第5頁(yè)
已閱讀5頁(yè),還剩211頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

從2012年初開(kāi)始學(xué)習(xí)和研究Go語(yǔ)言,雖精通,但總體上還是比較熟悉和了解的。這幾年踏踏實(shí)實(shí)讀著它的源碼一路走過(guò)來(lái),有GoC的底子。換句話說(shuō),拋開(kāi)goroutine等等時(shí)髦概念,其本質(zhì)上還是NextC的路子。這本筆記原則上力求簡(jiǎn)潔,屬于工具書(shū)而非。目的是在需要的時(shí)候,花上很短的時(shí)間就可從頭到尾復(fù)習(xí)完所有知識(shí)點(diǎn)。對(duì)熟練的程序員而言,工具書(shū)似乎比更重要些。本書(shū)在不作者個(gè)利的情況下,可自由散播。?:不定期更新 聯(lián)系雨痕2012-01- Go2012-01- R602012-03- 升級(jí)到1.02012-06-151.0.22013-03- 升級(jí)到1.12013-12- 1.22014-05- 1.32014-06-05reflect2014-06- 第一部分語(yǔ) 第1章類(lèi) 變 常 基本類(lèi) 類(lèi) 類(lèi)型轉(zhuǎn) 字符 指 自定義類(lèi) 第2章表達(dá) 保留 運(yùn)算 初始 控制 第3章函 函數(shù)定 變 返回 函 延遲調(diào) 錯(cuò)誤處 第4章數(shù) 第5章方 方法定 5.2字 方法 表達(dá) 第6章接 接口定 執(zhí)行機(jī) 接口轉(zhuǎn) 接 第7章并 第8章 工作空 源文 包結(jié) 文 第9章進(jìn) 內(nèi)存布 指針陷 第二部分源 Memory 初始 分配流 釋放流 其 Garbage 2.1回 內(nèi)存釋 狀態(tài)輸 Goroutine 初始 創(chuàng)建任 執(zhí)行任 連續(xù) 系統(tǒng)調(diào) 系統(tǒng) 178狀態(tài)輸 第三部分附 工 工具 條件編 跨平臺(tái)編 調(diào) Data 測(cè) .5.第一部分語(yǔ)言第1章類(lèi)型變Govar定義變量,自動(dòng)初始化為零值。如果提供初始化值,可省略變量類(lèi)型,由varvarxvarffloat32=1.6vars="abc"在函數(shù)內(nèi)部,可用更簡(jiǎn)略的":="funcfuncmain()x:=}//varvarx,y,zvars,n="abc",var)funcmain()n,s:=0x1234,println(x,s,}o,data,data,i:=[3]int{0,1,2},i,data[i]=2,//(i=0)->(i=2),(data[0]=特殊只寫(xiě)變量"_"funcfunctest()(int,{return1,}funcmain()_,s:=test()}varvarsfunc{i:=}Errorideclaredandnotused。(可使用"_i規(guī)避s:="abc"s:="abc"s,y:= o",println(&s,重新賦值與前s通常函數(shù)多返回值err{s,z:=1000,println(&s,定義新同名變量}f30f18常constconstx,yint=1,consts= o,const=10,bool=))funcmain()constx=} 不支持1UL、2LLconstconst)=//x=常量值還可以是len、cap、 constconst = = =)constconst)byte=int=//intto//float64toint,const)iotaconst)Sunday=023456constconst)=int64=1<<(10*//iota=//iota=與KBiota=在同一常量組中,可以提供多個(gè)iotaconstconstA,B=iota,iota<< //0,0<<C, //1,1<<)iotaconstconst)===//////c4,顯式恢復(fù)。注意計(jì)數(shù)包含了C、D//typetypeColorconstBlackColor=iota)functest(cColor){}funcmain(){c:=Blackx:=test(x)//Error:cannotusex(typeint)astypeColorinfunction}更明確的數(shù)字類(lèi)型命名,支持Unicode11040UnicodeCodePoint,int,403264int8,10-128~127,0~int16,20-32768~32767,0~int32,40-21~21億0~42int64,804884足以指針的uint32或uint64整UTF-8支持八進(jìn)制、十六進(jìn)制,以及科學(xué)記數(shù)法。標(biāo)準(zhǔn)庫(kù)matha,a,b,c,d:=071,0x1F,1e9,空指針值nil,而非C/C++NULL類(lèi)類(lèi)型包括slice、map和channel。它們有復(fù)雜的內(nèi)部結(jié)構(gòu),除了申請(qǐng)內(nèi)存外,還需newmake會(huì)被編譯器翻譯aa:=[]int{0,0,a[1]=b:=make([]int,b[1]=//slice.goc:c:=c[1]=//Error:invalidoperation:c[1](indexoftypevarbbyte=//varnint=bvarnint=int(b)

//Error:cannotuseb(typebyte)astypeintin<-chanint(c)(<-chanint)(c)

//相當(dāng)于相當(dāng)于<-(chanboola:=ifa

//Error:non-boola(typeint)usedasif}字符字符串是不可變值類(lèi)型,內(nèi)部用指針指向UTF-8默認(rèn)值是空字符串""用索引號(hào)某字節(jié),如s[i]不能用序號(hào)獲取字節(jié)元素指針。&s[i]struct{struct{ 使用索引號(hào)字符(byte)ss:=println(s[0]=='\x61',s[1]=='b',s[2]==truetruetrue使用"`"s:=`as:=`a輸出c連接跨行字符串時(shí),"+" ss:=o,"s2:=o,+//Error:invalidoperation:+untypedss:=o,s1:=s2:=s3:=o////UnicodeCodePoint\uFFFF、\U7FFFFFFF、\xFF格式。對(duì)應(yīng)rune類(lèi)型,UCS-4。funcfuncmain()fmt.Printf("%T\n",varc1c2rune\u6211'們println(c1我string(c2}truerune是int32要修改字符串,可先將其轉(zhuǎn)換成[]rune或[]byte,完成后再轉(zhuǎn)換為string。無(wú)論哪種轉(zhuǎn) funcfuncmain()s:=bs:=bs[1]=u電腦usus:=us[1]='話'}輸出forbyterunefuncfuncmain()s"abc漢字fori:=0;i<len(s);{fmt.Printf("%c,",}//for_,r:=range{fmt.Printf("%c,",//}指支持指針類(lèi)型*T,指針的指針**T,以及包含包名前綴的*<package>.TnilNULL操作符"&"取變量地址,"*"透過(guò)指針目標(biāo)對(duì)象不支持指針運(yùn)算,不支持"->"運(yùn)算符,直接用"."目標(biāo)成員funcfuncmain()typedatastruct{aintvard=data{1234}varp*datap=fmt.Printf("%p,fmt.Printf("%p,%v\n",p, }0x2101ef018,0x2101ef018,xx:=p:=&x//Error:invalidoperation:p+=1(mismatchedtypes*intand可以在unsafe.Pointerfuncfuncmain()x:=p:=unsafe.Pointer(&x)n:=(*[4]byte)(p)//*int->//Pointer->fori:=0;i<len(n);{fmt.Printf("%X",}}78785634返回局部變量指針是安全的,編譯器會(huì)根據(jù)需要將其分配在GCHeapfunctest(){x:=return

使用runtime.new分配x}將Pointer轉(zhuǎn)換成uintptrfuncfuncmain()d:=struct }{"abc",p:=uintptr(unsafe.Pointer(&d)) //*struct->Pointer->uintptrp+=unsafe.Offsetof(d.x) //uintptr+offsetp2:=unsafe.Pointer(p)px:=(*int)(p2)*px=

//uintptr->//Pointer->//d.x=fmt.Printf("%#v\n",}structstruct{sstring;xint}{s:"abc",注意:GC把uintptr當(dāng)成普通整數(shù)對(duì)象,它無(wú)法"關(guān)聯(lián)"對(duì)象被回收bool、int、stringarray、slice、map等和具體元素類(lèi)型、長(zhǎng)度等有關(guān),屬于未命名類(lèi)型。具有相同元素類(lèi)型和長(zhǎng)度的array具有相同元素類(lèi)型的slice具有相同鍵值類(lèi)型的map具有相同元素類(lèi)型和傳送方向的channel具有相同字段序列(字段名、類(lèi)型、、順序)的struct簽名相同(參數(shù)和返回值,不包括參數(shù)名稱(chēng))的function(方法名、方法簽名相同,和次序無(wú)關(guān))的interfacevarastruct{xint`a`}varvarastruct{xint`a`}varbstruct{xint`ab`}//cannotusea(typestruct{xint"a"})astypestruct{xint"ab"}inassignmentb=atypefuncfuncmain()typebigintvarxbigint=100}x:=varbbigint=bigint(x)varb2int64=int64(b)

varsmyslice=[]int{1,2,3}vars2[]int=s

第2章表達(dá)式保留運(yùn)算+&()-|<[]*^>{}/=,;%!.: *+/-&|<^&<&=|=^==NOTa0a1<<:a1<<:a=a&^清除bit6 nn:=p:=//b:=//ifn++==1////syntax//syntax//syntax//沒(méi)有"~",取反運(yùn)算也用"^"xx:=x,//0001,-初始////varastruct{xint}={100 //syntax//varb[]int={1,2,3//syntax//c:=struct{xint;y//////syntaxerror:unexpectedsemicolonorvara=struct{xintvarb=[]int{1,2,","",""}"aa:=2//Error:needtrailingcommabeforenewlineincomposite}a[]int{,//b//控制xx:=//ifx>//////Error:missingconditioninififn:="abc";x>0}elseifx<{}elseprintln("init"注意elseif和else不支持三元操作符"abab"whiless:=forin0len(s)ini+ 常見(jiàn)的for}n:=len(s)forn>0}替代whilen0替代forn0;{替代while(true替代forfuncfunclength(sstring) length.")return}funcmain()s:=forin0length(s)ini+ 避免多次調(diào)用lengthprintln(i,}}callcall0123(索引,值)(鍵,值)1st1st2nd unicode,"_"ss:=fori:=range{)忽略2ndvalue,支持string/array/slice/mapfor_,c:=range{}忽略indexm:=map[string]int{"a":1,"b":fork,v:=rangem{ (keyvalue)。println(k,v)}注意,range會(huì)對(duì)象aa:=[3]int{0,1,fori,v:=rangea//index、value都是 ifi==0a[1],a[2]=999,}確認(rèn)修改有效,輸出[0999999]a[i]=v+//使 品中取出的value修改原數(shù)組} 輸出[100101102] ss:=[]int{1,2,3,4,forfori,v:=rangesstructslicepointerlencapifi==0s=s[:3]s[2]=100}對(duì)slicerangeprintln(i,}001234另外兩種類(lèi)型map、channel是指針包裝,而不像slice是struct分支表達(dá)式可以是任意類(lèi)型,不限于常量。可省略breakxx:=[]int{1,2,i:=switchicasecase1,3:}aa如需要繼續(xù)下一分支,可使用fallthroughxx:=switch{casecase0:}if...elseif...elseswitchswitchcasex[1]>0:casex[1]<0:}switchi:={casei>casei<0:}Goto,Break,支持在函數(shù)內(nèi)goto跳轉(zhuǎn)。名區(qū)分大小寫(xiě),未使用錯(cuò)誤funcfuncmain()variintfor{ifi>2{gotoBREAK}//Error:labelEXITdefinedandnot 配合,break和continue可在多級(jí)嵌套循環(huán)中跳出funcfunc{forx:=0;x<3;x++fory:=0;y<5;y++ify>2{continueL2}ifx>1{breakL1}print(x,":",y,"}}}0:00:00:11:01:1附:break可用于for、switch、select,而continue僅能用于forxx:={casex>=ifx==0{break第3章函數(shù)不支持嵌套(nested)、重載(overload)和默認(rèn)參數(shù)(defaultparameter)使用關(guān)鍵字funcfunctest(x,yint,sstring)(int,{n:=x+returnn,fmt.Sprintf(s,

}funcfunctest(fnfunc()int){return}typeFormatFuncfunc(sstring,x,yint)funcformat(fnFormatFunc,sstring,x,yint){returnfn(s,x,}funcmain()s1:=test(func()int{return100//直接 s2:=format(func(sstring,x,yint){returnfmt.Sprintf(s,x,},"%d,%d",10,println(s1,}變變參本質(zhì)上就是slicefuncfunctest(sstring,){varxfor_,i:=range{x+=}returnfmt.Sprintf(s,}funcmain()println(test("sum:%d",1,2,}slicefuncfuncmain()s:=[]int{1,2,println(test("sum:%d",}返回"_"funcfunctest()(int,{return1,}funcmain()//s:=make([]int,//s= //Error:multiple-valuetest()insingle-valuex,_:=test()}funcfunctest()(int,{return1,}funcadd(x,yint){returnx+}funcsum(){varxfor_,i:=range{x+=}return}funcmain()}命名返回參數(shù)可看做與形參類(lèi)似的局部變量,最后由returnfuncfuncadd(x,yint)(z{z=x+y}funcmain()println(add(1,}funcadd(x,yint)(zint){varz=x+returnz

//不能在一個(gè)級(jí)別 "zredeclaredinthisblock"錯(cuò)誤//Error:zisshadowedduring}}命名返回參數(shù)允許defer延遲調(diào)用通過(guò)閉包和修改funcfuncadd(x,yint)(z{deferfunc(){z+=100z=x+y}funcmain()println(add(1 輸出}顯式returnfuncfuncadd(x,yint)(z{deferfunc() 輸出z=x+returnz+執(zhí)行順序zz200(calldefer}funcmain()println(add(1 輸出}3.4函函數(shù)可賦值給變量,做為結(jié)構(gòu)字段,或者在channel////functionvariable--fn:=func(){println(" o,World!")}//functioncollection--fns:=[](func(xint)func(xint)int{returnx+1},func(xint)int{returnx+2}}//functionasfieldd:=struct{fnfunc()fn:func()string{return o,World!"}//channeloffunctionfc:=make(chanfunc()string,2)fc<-func()string{return" o,World!"}funcfunctest(){x:=fmt.Printf("x(%p)=%d\n",&x,returnfunc()fmt.Printf("x(%p)=%d\n",&x,}}funcmain()f:=test()}xx(0x2101ef018)=100x(0x2101ef018)=在匯編層面,test實(shí)際返回的是FuncVal對(duì)象,其中包含了函數(shù)地址、閉包對(duì)象指FuncVal{func_address,closure_var_pointer... 關(guān)鍵字defer用于延遲調(diào)用。這些調(diào)用直到ret前才被執(zhí)行,通常用于釋放資源或錯(cuò)funcfunctest()errorf,err:=os.Create("test.txt")iferr!=nil{returnerr}defer return}多個(gè)defer,按FILO次序執(zhí)行。哪怕函數(shù)或某個(gè)延遲調(diào)用發(fā)生錯(cuò)誤,這些調(diào)用依舊funcfunctest(x{deferprintln("a")deferdefer{println(100//div0異常 defer}funcmain()}panic:runtimeerror:integerdivideby延遲調(diào)用參數(shù)在時(shí)求值或,可用指針或閉包"延遲"funcfunctest()x,y:=10,deferfunc(i{println("defer:",yxx+=y+=println("x=",x,"y=",}xx=20y=defer:10defer可能會(huì)導(dǎo)致性能問(wèn)題,尤其是在一個(gè)"大循環(huán)"里。varvarlockfunctest()}func{lock.Lock()}func arkTest(b{fori:=0;i<b.N;i++{}}func arkTestDefer(b{fori:=0;i<b.N;i++{}}輸出 43128沒(méi)有結(jié)構(gòu)化異常,使用panic拋出錯(cuò)誤,recoverfuncfunctest()deferdeferfunc()iferr:=recover();err!=nil{}將panic("panic}由于panic、recover參數(shù)類(lèi)型為interface{}funcpanic(vinterface{})funcfuncpanic(vinterface{})funcrecover()interface{}funcfunctest()defer{defer{panic("deferpanic("test}func{deferdeferrecovernil。任何未funcfunctest()deferdeferfunc(){func()panic("test}func{}deferdeferpanic:testfuncfunc{}functest()deferexcept()}funcfunctest(x,y{varzfunc()deferfunc()ifrecover()!=nil{z=0z=x/yprintln("x/y=",}除用panic中斷性錯(cuò)誤外,還可返回error類(lèi)型錯(cuò)誤對(duì)象來(lái)表示函數(shù)調(diào)用狀態(tài)typetypeerror{Error() error.Newfmt.Errorferror接口的錯(cuò)誤對(duì)象。通過(guò)判斷錯(cuò)varvarErrDivByZero=errors.New("divisionbyfuncdiv(x,yint)(int,error)ify==0{return0,ErrDivByZero}returnx/y,nil}funcmain()switchz,err:=div(10,0);{case}}如何區(qū)別使用panic和error兩種方式?慣例是:在包panic,對(duì)外API使error第4章數(shù)據(jù)數(shù)組長(zhǎng)度必須是常量,且是類(lèi)型的組成部分。[2]int和[3]int支持"=="、"!="指針數(shù)組[n]*T,數(shù)組指針*[n]Taa:=[3]int{1,b:=[...]int{1,2,3,c:=[5]int{2:100,//未初始化元素值為0d:={namestringageuint8{"user1",{"user2",}aa:=[2][3]int{{1,2,3},{4,5,b:=[...][2]int{{1,1},{2,2},{3,//第2緯度不能用"..."值拷貝行為會(huì)造能問(wèn)題,通常會(huì)建議使用slice,或數(shù)組指針funcfunctest(x{fmt.Printf("x:%p\n",&x)x[1]=1000}funcmain()a:=fmt.Printf("a:%p\n",}a:a:0x2101f9150x:0x2101f9170[00]lencap(元素?cái)?shù)量)aa:=println(len(a), //2,需要說(shuō)明,slice并不是數(shù)組或數(shù)組指針。它通過(guò)內(nèi)部指針和相關(guān)屬性數(shù)組片段,以structstruct{//mustnotmove//actual//numberof//allocatednumberof屬性len表示可用元素?cái)?shù)量,讀寫(xiě)操作過(guò)該限制屬性cap表示最大擴(kuò)張容量,出數(shù)組限制slice==nillen、cap0datadata:=[...]int{0,1,2,3,4,5,slice:=//[low:high:+- high- +- len=high-lowcap=max- data|0|1|2|3|4|5|6 slice|pointer|len=3|cap=4|<len ++|||< |||||+++<<<slice.arraypointer data:=[...]int{0,1,2,3,4,5,6,7,8, ++++123468省略67855省略high、max1123456783省略low、maxdatadata:=[...]int{0,1,2,3,4,s:=data[2:4]s[0]+=100s[1]+=[102[102[011022034slices1s1:=[]int{0,1,2,3,8:fmt.Println(s1,len(s1),//s2:=make([]int,6,fmt.Println(s2,len(s2),使用make創(chuàng)建,指定len和caps3:=make([]int,fmt.Println(s3,len(s3),省略cap,相當(dāng)于caplen12300099000068000066使用make動(dòng)態(tài)創(chuàng)建slice,避免了數(shù)組必須用常量做長(zhǎng)度的麻煩。還可用指針直接 ss:=[]int{0,1,2,pp:=*p+=*int[0[01102至于[][]T,是指元素類(lèi)型為[]Tdatadata:=[]int{1,2,[]int{100,[]int{11,22,33,}resliceslice創(chuàng)建新slicecapss:=[]int{0,1,2,3,4,5,6,7,8,s1:=s2:=s3:=//[23//[456//data|0|1|2|3|4|5|6|7|8|9 |2|3|4 len=3,cap= |4|5|6|7 len=4,cap= |7|8|X error:sliceboundsoutofss:=[]int{0,1,2,3,4,5,6,7,8,s1:=s1[2]=//[23s2:=//[10056s2[3]s2[3]=[0123100562008 sliceslicess:=make([]int,0,5)fmt.Printf("%p\n",s2:=append(s,1)fmt.Println(s,[]簡(jiǎn)單點(diǎn)說(shuō),就是在array[slice.high]datadata:=[...]int{0,1,2,3,4,5,6,7,8,s:=s2:=append(s,100,121002005678112100一旦超出原slice.capdatadata:=[...]int{0,1,2,3,4,10:s:=s=append(s,100,一次append兩個(gè)值,超出s.capfmt.Println(s,fmt.Println(s,fmt.Println(&s[0] [0[01100200][01234000000]0x20819c1800x20817c0c0從輸出結(jié)果可以看出,append后的s重新分配了底層數(shù)組,并數(shù)據(jù)。如果只追加一個(gè)值,則不會(huì)超過(guò)s.cap限制,也就不會(huì)重新分配。通常以2倍容量重新分配底層數(shù)組。在大批量添加數(shù)據(jù)時(shí),建議分配足夠大的空間,以減少內(nèi)存分配和數(shù)據(jù)開(kāi)銷(xiāo)?;虺跏蓟銐蜷L(zhǎng)的len屬性,改用索引號(hào)進(jìn)行操作。及時(shí)釋放不再使用的slice對(duì)象,避免持有過(guò)期數(shù)組,造成GC無(wú)法回收。ss:=make([]int,0,1)c:=cap(s)fori:=0;i<50;{s=append(s,ifn:=cap(s);n>{fmt.Printf("cap:%d->%d\n",c,n)c=n}}輸出1-22-44-88-16->32->函數(shù)copy在兩個(gè)slice間數(shù)據(jù),長(zhǎng)度以len小的為準(zhǔn)。兩個(gè)slice可指向同一底層數(shù)組,允許元素區(qū)間。datadata:=[...]int{0,1,2,3,4,5,6,7,8,s:=s2:=copy(s2,copy(s2,//dst:s2,[8[8923[892345678應(yīng)及時(shí)將所需數(shù)據(jù)copy到較小的slice類(lèi)型,哈希表。鍵必須是支持相等運(yùn)算符(==、!=)類(lèi)型,比如number、string、pointer、array、struct,以及對(duì)應(yīng)的interface。值可以是任意類(lèi)型,沒(méi)有限制。mm:={namestringageint{"user1",{"user2",}make函數(shù)一個(gè)合理元素?cái)?shù)量參數(shù),有助于提升性能。因?yàn)槭孪壬暾?qǐng)一大塊內(nèi)存,mm:=make(map[string]int,mmmap[string]int{":}判斷keyifv,ok:=m["a"];{對(duì)于不存在的key,直接返回\0m["b"]m["b"]=delete(m,key獲取鍵值對(duì)數(shù)量。capfork,v:=range{println(k,}從map中取回的是一個(gè)value臨時(shí)品,對(duì)其成員的修改是沒(méi)有任何意義的typetypeuserstruct{namestringmmap[int]user{:m[1].name=//Error:cannotassigntouu:=="Tom"m[1]=u替換valuem2map[int]*user{1:}//返回的是指 forfori:=0;i<5;{m0:"a",1:"a",2:"a",3:"a",4:5:"a",6:"a",7:"a",8:"a",9:}fork:=range{m[k+k]=}}}map[12:xmap[12:x16:x2:x6:x10:x14:x18:x]map[12:x16:x20:x28:x36:x]map[12:x16:x2:x6:x10:x14:x18:x]map[12:x16:x2:x6:x10:x14:x18:x]map[12:x16:x20:x28:x36:x]值類(lèi)型,賦值和傳參會(huì)全部?jī)?nèi)容??捎?_"定義補(bǔ)位字段,支持指向自身類(lèi)型的指針typetypeNodestruct data*bytenext}funcmain()n1:= }n2:= data:nil,next:}}typetypeUser{namestringageint}u1:=User{"Tom",u2u2:= //Error:toofewvaluesinstructtypetypeFile{namestringsizeintattrstructpermintowner}}f:=size:1025,//attr:{0755, //Error:missingtypeincomposite}f.attr.owner=f.attr.perm=varattr={perm ownerint}{2,f.attr="=="、"!="maptypetypeUser{idintnamestring}mmap[User]int{,"Tom"}: varvaru1struct{namestring"username"}varu2struct{namestring}u2= //Error:cannotuseu1(typestruct{namestring"username"}) typestruct{namestring}in"節(jié)省"set"狀態(tài)""靜varvarnullset:=make(map[string]struct{})set["a"]=null(不含包名的字段。typetypeUser{name}typeManagerstructtitle}m:=User:User{"Tom"},} typetypeResource{id}typeUserstruct}typeManager{titletitle}varmManagerm.id=1="Jack"m.title=typetypeResource{idintnamestring}typeClassify{id}typeUser{Resourcenamestring}Resource.id與Classify.id遮蔽Ru:=} //U:Jack //people////Error:ambiguousselector//typetypeResource{id}typeUserstruct////name//Error:duplicatefield}u:=}面向?qū)ο笕筇卣骼? typetypeUser{idintnamestring}typeManagerstructtitle}m:=Manager{User{1,"Tom"},//varuUser= //Error:cannotusem(typeManager)astypeUserinvaruUser Cstructobject|<|<User:24>|<--title:16-- m +|+++1|||||Administrator| |+ | u | |<-id:8-->|<-name:16-- | | 可用unsafe : :0x:m.title:b0,size:40,align:b0,offset:b8,offset:c8,offset:第5章方法方法總是綁定對(duì)象實(shí)例,并隱式將實(shí)例作為第一實(shí)參(receiver)參數(shù)receiverreceiverT*TT不支持方法重載 value或pointertypetypeQueue{elements}funcNewQueue()*Queuereturn&Queue{make([]interface{},func(*Queue)Push(einterface{}){panic("not}省略receiver//func(Queue)Push(eint)error//Error:methodredeclared: panic("not//func(self*Queuelength(int receiver參數(shù)名可以是self、thisreturn}receiverT和*Ttypetypestruct{x}func(selfData){fmt.Printf("Value://funcValueTest(self}}func(self*Data){fmt.Printf("Pointer:%p\n",//funcPointerTest(selffuncmain()d:=Data{}p:=&dfmt.Printf("Data:%p\n",////////}Data:0x2101ef018Value:0x2101ef028Pointer:Data:0x2101ef018Value:0x2101ef028Pointer:0x2101ef018Value:Pointer:字 typetypeUser{idintnamestring}typeManager{}func(self*User)ToString()string{ //receiver=&(Manager.User)returnfmt.Sprintf("User:%p,%v",self,self)}funcmain()m:=Manager{User{1,fmt.Printf("Manager:%p\n",}Manager:Manager: :b0,&{1名方法,就可以實(shí)現(xiàn)"override"。typetypeUser{idintnamestring}typeManagerstructtitle}func(self*User)ToString()stringreturnfmt.Sprintf("User:%p,%v",self,}func(self*Manager)ToString()stringreturnfmt.Sprintf("Manager:%p,%v",self,}funcmain()m:=Manager{User{1,"Tom"},}Manager:Manager: :b0,&{{1Tom}b0,&{1方法TreceiverT*TreceiverT+*T如類(lèi)型S包含字段T,則S方法集包含T方法如類(lèi)型S包含字段*T,則S方法集包含T+*T方法T*T,*ST+*T用實(shí)例value和pointer調(diào)用方法(含字段)不受方法集約束,編譯器總是查找全部方法,并自動(dòng)轉(zhuǎn)換receiver實(shí)參。表達(dá)instance.method(args...)><type>.func(instance, methodvaluemethodexpressionmethodvaluemethodexpression則須顯式傳參。typetypeUser{idintnamestring}func(self*User){fmt.Printf("%p,%v\n",self,}funcmain()u:=User{1,"Tom"}mValue:=//隱式傳遞mExpression:=//顯式傳遞},&{1,&{1,&{1需要注意,methodvalue會(huì)receivertypetypeUser{idintnamestring}func(selfUser){}funcmain()u:=User{1,"Tom"}mValue:=u.Testu.id,=2,"Jack"}{2{2{1在匯編層面,methodvalue和閉包的實(shí)現(xiàn)方式相同,實(shí)際返回FuncValFuncVal{method_address,receiver_copy 可依據(jù)方法集轉(zhuǎn)換methodexpression,注意receivertypetypeUser{idintnamestring}func(self*User){fmt.Printf("TestPointer:%p,%v\n",self,}func(selfUser){fmt.Printf("TestValue:%p,%v\n",&self,}funcmain()mvmv:=User.TestValuemp:=(*User).TestPointermp2:=(*User).TestValue}*User方法集包含TestValuefuncTestValue(self*User)receivervaluecopy:TestValue:0xTestPointer:TestValue:,{1,{1,&{1c0,{1"還原"typetypeDatafunc(Data)func(*Data)TestPointer()funcmain()varp*Data=nil(*Data)(nil).TestPointer()//methodvalue //methodexpression// //invalidmemoryaddressornilpointer//(Data)(nil).TestValue()//cannotconvertniltotype// //cannotusenilastypeDatainfunction}第6章接口就表示它"實(shí)現(xiàn)"了該接口,無(wú)須在該類(lèi)型上顯式添加接口。(不包括參數(shù)名以及返回值。當(dāng)然,該類(lèi)型還ertypetypeStringer{String()}typePrinter{Stringer}typeUser{idintnamestring}func(self*User)String()stringreturnfmt.Sprintf("user%d,%s",self.id,}func(self*User){}funcmain()vartPrinter=&User{1,"Tom"} *UserString、Print。}user1, interface{}沒(méi)有任何方法簽名,也就意味著任何類(lèi)型都實(shí)現(xiàn)了空接口。其作用類(lèi)似面向?qū)ο笳Z(yǔ)言中的根對(duì)象object。funcfuncPrint(v{fmt.Printf("%T:%v\n",v,}funcmain() o,}int:int:o,typetypeTester{sinterface{String()string}}typeUser{idintnamestring}func(self*User)String()stringreturnfmt.Sprintf("user%d,%s",self.id,}funcmain()t:=Tester{&User{1,"Tom"}}}user1, (interfacetable)structstruct{ struct{voidtypetypeUser{idintnamestring}funcmain()u:=User{1,"Tom"}variinterface{}=uu.id=2="Jack"fmt.Printf("%v\n",u)}{2{2{1typetypeUser{idintnamestring}funcmain()u:=User{1,varvi,piinterface{}=u,//vi.(User).name="Jack"pi.(*User).name="Jack"http://Error:cannotassigntofmt.Printf("%v\n",fmt.Printf("%v\n",}{1Tom}{1Tom}tabdatanilnilvarvarainterface{}=varbinterface{}=//tab=nil,data=tab包含*int類(lèi)型信息datatypeiface{itab,data}ia:=*(*iface)(unsafe.Pointer(&a))ib:=fmt.Println(a==nil,fmt.Println(b==nil,ib,輸出truetrue{0false{5057280}typetypeUser{idintnamestring}}func(self*User)String()stringreturnfmt.Sprintf("%d,%s",self.id,}funcmain()varointerface{}=&User{1,ifi,ok:=o.(fmt.Stringer);{}//ok-u:=//u:=o.(User)//panic:interfaceis*main.User,not}還可用switch做批量類(lèi)型判斷,不支持fallthroughfuncmain()varointerface{}=&User{1,switchv:={casecasefmt.Stringer:casefunc()string:case*User:fmt.Printf("%d,%s\n",v.id,)

//o==//////}}typetypeStringer{String()}typePrinter{String()string}typetypeUser{idintnamestring}func(self*User)String()stringreturnfmt.Sprintf("%d,%v",self.id,}func(self*User){}funcmain()varoPrinter=&User{1,"Tom"}varsStringer=o}接var_fmt.Stringer= "實(shí)現(xiàn)"typetypeTester{}typeFuncDofunc(selfFuncDo)Do(){self()funcmain()vartTester=FuncDo(func(){println("}o,World!")第7章并發(fā)Go在語(yǔ)言層面對(duì)并發(fā)編程提供支持,一種類(lèi)似協(xié)程,稱(chēng)作goroutine只需在函數(shù)調(diào)用語(yǔ)句前添加go關(guān)鍵字,就可創(chuàng)建并發(fā)執(zhí)行單元。開(kāi)發(fā)人員無(wú)需了解任何執(zhí)行細(xì)節(jié),調(diào)度器會(huì)自動(dòng)將其安排到合適的系統(tǒng)線程上執(zhí)行。goroutine是一種非常輕量事實(shí)上,函數(shù)main就以goroutine運(yùn)行。另有與之配套的channel類(lèi)型,用以實(shí)現(xiàn)"以通訊來(lái)共享內(nèi)存"的CSP模式。相關(guān)實(shí)現(xiàn)細(xì)節(jié)可參考本書(shū)第二部分的源碼剖析。gogofunc()o,調(diào)度器不能保證多個(gè)goroutine默認(rèn)情況下,進(jìn)程啟動(dòng)后僅允許一個(gè)系統(tǒng)線程服務(wù)于goroutine。可使用環(huán)境變量或標(biāo)準(zhǔn)runtime.GOMAXPROCS修改,讓調(diào)度器用多個(gè)線程實(shí)現(xiàn)多核并行,而不僅僅是并發(fā)。funcfuncsum(id{varxfori:=0;i<math.MaxUint32;{x+=}println(id,}funcmain()wg:=new(sync.WaitGroup)fori:=0;i<2;{gofunc(idint){deferwg.Done()}}}$$gobuild-o$time-p 程序開(kāi)始到結(jié)束時(shí)間差(非CPU時(shí)間用戶態(tài)所使用CPU時(shí)間片(多核累加CPU$GOMAXPROCS=2time-p01552個(gè)核并行,real調(diào)用runtime.Goexit將立即終止當(dāng)前goroutine執(zhí)行,調(diào)度器確保所有已funcfuncmain()wg:=new(sync.WaitGroup)gofunc()deferdeferfunc()//終止當(dāng)前}和協(xié)程yield作用類(lèi)似,Gosched讓出底層線程,將當(dāng)前goroutine暫停,放回隊(duì)列等f(wàn)uncfuncmain()wg:=new(sync.WaitGroup)gofunc()deferfori:=0;i<6;{ifi==3{runtime.Gosched()}gofunc()deferwg.Done() }$$gorunmain.go123o,45channelCSPgoroutine通訊。其內(nèi)部實(shí)現(xiàn)了funcfuncmain()data:=make(chanint)exit:=make(changofunc()ford:=range{}closefmt.Println("recvexit<-data<-data<-data<-3fmt.Println("send}1123sendover.recvchannel可減少排隊(duì)阻塞,具備更高的效率。但應(yīng)該考慮使用指針規(guī)funcfuncmain()data:=make(chanint,3)exit:=make(chanbool)//3data<-data<-data<-gofunc()ford:=range{}}exit<-data<-data<-5}varvara,bchanint=make(chanint),make(chanint,rangeok-idiomchannelforforifd,ok:=<-data;{}else}}向closedchannel發(fā)送數(shù)據(jù)panic錯(cuò)誤,接收立即返回零值。而nilchannel,無(wú)內(nèi)置函數(shù)len返回未被的緩沖元素?cái)?shù)量,cap返回緩沖區(qū)大小d1:=make(chanint)d1:=make(chanint)d2:=make(chanint,3)d2<-fmt.Println(len(d1),cap(d1))fmt.Println(len(d2),//0//1可以將channelcc:=make(chanint,varsendchan<-int=c //send-onlyvarrecv<-chanint=c send<-//<-//Error:receivefromsend-onlytypechan<-//recv<-//Error:sendtoreceive-onlytype<-chan不能將單向channel轉(zhuǎn)換為普通channeldd:=(chand:=(chan//Error:cannotconverttypechan<-inttotypechan//Error:cannotconverttype<-chaninttotypechanchannelselectchannel做收發(fā)操作,或執(zhí)行defaultcase。funcfuncmain()a,b:=make(chanint,3),make(changofunc()v,ok,s:=0,false,forselect{ channel,接收數(shù)據(jù)。casev,ok=<-a:s="a"casev,ok=<-b:s=}ifokfmt.Println(s,}else}}fori:=0;i<5;i++selectchannelcasecasea<-i:caseb<-}}channelmaingoroutine}bbaaab在循環(huán)中使用selectdefaultcase需要,避免形成洪水用簡(jiǎn)單工廠模式打包并發(fā)任務(wù)和channelfuncfuncNewConsumer()chan{data:=make(chanint,gofunc()ford:=range{}return}funcmain()data:=data<-data<-2select}channel(semaphore)funcfuncmain()wg:=sync.WaitGroup{}sem:=make(chanint,fori:=0;i<3;{gofunc(idint){defersem<-向semforx:=0;x<3;{fmt.Println(id,} goroutine}}$GOMAXPROCS=2run000102101112202122closedchannelfuncfuncmain()varwgsync.WaitGroupquit:=make(chanbool)fori:=0;i<2;{gogofunc(id{defertask:=func()}for{{case<-}}closedchannel}time.Sleep(time.Second* goroutine}用select實(shí)現(xiàn)超時(shí)(timeout)funcfuncmain()w:=make(chanbool)c:=make(chanint,2)gofunc()selectcasev:=<-c:case<-time.After(time.Second*3):}w<-//c<-//}channel(內(nèi)部實(shí)現(xiàn)為指針)typeRequeststruct data[]intretdata[]intretchanint}funcNewRequest()*Requestreturn&Request{data,make(chanint,1)}funcProcess(req{x:=for_,i:=range{x+=}req.ret<-}funcmain()req:=NewRequest(10,20,30)}第8章包 有嚴(yán)格要求,每個(gè)工作空間(workspace)必須由bin、pkg、src三 |+|+//goinstall安 ||||+|//gobuild生成靜態(tài)庫(kù)(.a)存 |||||||||+|+|+|++|。+ +||+|+|+|+可在GOPATH環(huán)境變量列表中添加多個(gè)workspace,但不能和GOROOTexport 通常goget使用第一個(gè)workspace保存的第庫(kù)源文UTF-8格式,否則會(huì)導(dǎo)致編譯器出錯(cuò)。結(jié)束:語(yǔ)句以";"結(jié)束,多數(shù)時(shí)候可以省略。注釋?zhuān)褐С?http://"、"/**/"命名:采用camelCasing包結(jié)所有代碼都必須組織在package源文件頭部以"package<name>"包名稱(chēng) 包名類(lèi)似namespace,與包所 可執(zhí)行文件必須包含packagemain,函數(shù)main說(shuō)說(shuō)明:osArgs返回命令行參數(shù),osExit要獲取正確的可執(zhí)行文件路徑,可用filepathAbs(execLookPath(osArgs[0]))public:首字母大寫(xiě),可被包外 使用包成員前,必須先用importimportimport"相 /包主文件名相 是指 importimport->import"os/exec"-> import"yuhen/test"importM"yuhen/test"importimport"yuhen/test"importM"yuhen/test"import.import_默認(rèn)模式包重命名//簡(jiǎn)便模式非導(dǎo)入模式僅讓該執(zhí)行初始化函數(shù)。未使用的導(dǎo)入包,會(huì)被編譯器視為錯(cuò)誤(不包括"import_")./main.go:4:./main.go:4:importedandnotused:對(duì)于當(dāng) 下的子包,除使用默認(rèn)完整導(dǎo)入路徑外,還可使用local方式|+|+|+|+|+importimportimportgorunmain.go8.2.2在所有初始化函數(shù)結(jié)束后才執(zhí)行main.main因?yàn)闊o(wú)法保證初始化函數(shù)執(zhí)行順序,因此全局變量應(yīng)該直接用varvarvarnow=funcinit()fmt.Printf("now:%v\n",}funcinit()fmt.Printf("since:%v\n",}可在初始化函數(shù)中使用goroutinevarvarnow=funcmain()fmt.Println("main:",}funcinit()fmt.Println("init:",int(time.Now().Sub(now).Seconds()))w:=make(chanbool)gofunc()time.Sleep(time.Second*3)w<-true}init:init:main:文擴(kuò)展工具godoc(中間沒(méi)有空行)自動(dòng)轉(zhuǎn)換URL為自動(dòng)合并多個(gè)源碼文件中的package無(wú)法顯式packagemain建議用專(zhuān)門(mén)的doc.go保存package包文檔第一整句(中英文句號(hào)結(jié)束)被當(dāng)做packages只要Example oExampleT_M,ExampleUser,用了該文件中的其他成員,那么示例會(huì)顯示整個(gè)文件內(nèi)容,而不僅僅是測(cè)試函數(shù)自己非測(cè)試源碼文件中以BUG(author)開(kāi)始的注釋?zhuān)瑫?huì)在幫助文檔Bugs//BUG(yuhen):memory 第9章進(jìn)階 | |3.14| |1|2|3|4 ++++|pointer|len=5 +s=|||h|e|l|l|o ||+|pointer|len=2 sub=+++|1|2|0|0|3|0|0|0|struct{abyte;bbyte;cint32}={1,2,3 +++|pointera|b+struct{a*int;bint||+++|int++++++++|pointer|len=8|cap=8 +x=[]int{0,1,2,3,4,5,6,7|||0|1|2|3|4|5|6|7 || |pointer|len=2|cap=5|y= ++|++*itab+||++*data struct+|||Itab |data + +++|pointer++s=|||0|0|0 +++++|pointer|len=1|cap=3+slice=make([]int,1,|+++||0|0|0 ++|pointer++;|| .hashmap.cHmap ++|pointer++channelmake(chanint)|| .chan.cHchan 對(duì)象內(nèi)存分配會(huì)受編譯參數(shù)影響。舉個(gè)例子,當(dāng)函數(shù)返回對(duì)象指針時(shí),必然在堆上分配??扇绻摵瘮?shù)被內(nèi)聯(lián),那么這個(gè)指針就不會(huì)跨棧幀使用,就有可能直接在棧上分配,以實(shí)現(xiàn)代碼優(yōu)化目的。因此,是否內(nèi)聯(lián)對(duì)指針輸出結(jié)果有很大影響。unsafe.PointeruintptruintptrGC當(dāng)做普通整數(shù)對(duì)象,它不能所""對(duì)象被回收。typetypedatastructx[1024*}functest(){p:=return}funcmain()constN=cache:=fori:=0;i<N;{cache[i]=test()}}$gobuild-otest&&GODEBUG="gctrace=1"0->0->0->合法的unsafe.Pointerfuncfunctest(){p:=return}funcmain()constN=cache:=fori:=0;i<N;{cache[i]=test()}}$$gobuild-otest&&GODEBUG="gctrace=1"指向?qū)ο蟪蓡T的unsafe.Pointertypetypedatastruct [1024*100]byte }functest(){d:=return}funcmain()constN=cache:=fori:=0;i<N;{cache[i]=test()}}$gobuild-otest&&GODEBUG="gctrace=1"由于可以用unsafe.Pointer、uintptr創(chuàng)建"danglingpointer"等指針,所以在使用時(shí)需要特別。另外,cgoC.malloc等函數(shù)所返回指針,與GC無(wú)關(guān)。指針構(gòu)成的"循環(huán)"加上runtime.SetFinalizer會(huì)導(dǎo)致內(nèi)存typetypeDatastruct [1024*100]byte }functest()vara,ba.oa.o=b.o=runtime.SetFinalizer(&a,func(d*Data){fmt.Printf("a%pfinal.\n",d)})runtime.SetFinalizer(&b,func(d*Data){fmt.Printf("b%pfinal.\n",d)}func{for}}$gobuild-gcflags"-N-l"&&GODEBUG="gctrace=1"(1180-53)(2226-75)(4307-109)回收器能正確處理"指針循環(huán)",但無(wú)法確定Finalizer依賴(lài)次序,也就無(wú)法調(diào) 通過(guò)cgo,可在Go和C/C++代碼間相用。受CGO_ENABLED參數(shù)限制packagepackage#include<stdio.h> o() o,}importfuncmain() }cgo代碼很件很麻煩的事,建議單獨(dú)保存到.c文件中。這樣可以將其當(dāng)做獨(dú)立的#ifndef#ifndef#define#include"test.h" o() o,} 避免和Gmain(intargc,char return}packagepackage#includeimportfuncmain() }編譯和調(diào)試C$$gcc-g-D -otest由于cgo僅掃描當(dāng)前,如果需要包含其他C項(xiàng)目,可在當(dāng)前新建一個(gè)C文件,然后用#include指令將所需的.h、.c都包含進(jìn)來(lái),記得在CFLAGS中使用"-I"參數(shù)指定原路徑。某些時(shí)候,可能還需指定"-std"參數(shù)??墒褂?cgo命令定義CFLAGS、LDFLAGS#cgoCFLAGS:-#cgoCFLAGS:-

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論