版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、Go程序設計語言(一)本文譯自Rob Pike的Go語言PPT教程 "The Go Programming Language Part 1(updated June 2011)"。由于該教程的最新更新時間早于Go 1版本發(fā)布,因此該PPT中的一些內容與Go 1語言規(guī)范略有差異,到時我會在相應的地方做上注解。誰發(fā)明了GoGo語言的設計和實現工作是由Google的一個研發(fā)小組以及來自世界各地的大量貢獻者共同完成的。聯系方式:· :
2、 官網· : 用戶討論組· : 開發(fā)者討論組課程大綱第一部分:基礎第二部分:類型(type)、方法(method)以及接口(interface)第三部分:并發(fā)(concurrency)與通信(communication)這個課程是關于Go程序設計語言的,而不是關于編程語言設計方法的,后者是一個單獨的話題,不在此教程范圍內。第一部
3、分大綱· 動機· 基礎 - 簡單、熟悉的內容· 包與程序構建動機為什么要發(fā)明一門新語言?在當今世界,編程語言在某些方面不夠給力:· 計算機運行速度快,但軟件的構建慢。· 為了速度和安全性需進行必要的依賴分析。· 在類型上遇到了太多的阻礙。· 對垃圾收集以及并發(fā)的支持太差。· 多核被視為危機而不是機會。積極應對我們的目標是讓編程重新回歸快樂。· 兼有動態(tài)語言的感覺以及靜態(tài)類型系統(tǒng)的安全性;· 編譯成機器語言以獲得更快的運行速度;· 真正在運行時支持GC(垃圾收集)以及并發(fā);
4、183; 輕量級、靈活的類型系統(tǒng);· 擁有方法(method),但卻不是傳統(tǒng)的OO(面向對象)語言。資源關于Go語言的更多背景資料請參見文檔:文檔包括:· 語言規(guī)范· 教程· "Effective Go"· 標準庫文檔· 安裝和How-to文檔· FAQs· 一個語言聯系游樂場(在瀏覽器中運行Go程序)· 更多現狀:編譯器gc(Ken Thompson),又稱6g,8g,5g
5、0; 繼承自Plan 9項目的編譯器模型 生成代碼速度非???#160; 不支持gcc直接鏈接gccgo(Ian Taylor) 更為熟悉的體系架構 生成代碼的速度沒有gc那樣快 支持gcc直
6、接鏈接支持32-bit和64-bit x86 (amd64,x86-64) 以及ARM。垃圾收集器,并發(fā)等都已實現。優(yōu)秀且正逐步完善的標準庫。基礎是時候上一些代碼了package mainimport "fmt" func main() fmt.Print("Hello, 世界n") 語言基礎· 假設熟悉其他C語言類的(C-like)編程語言,這里將快速瀏覽一些基礎知識。· 這里大部分內容是簡單的且熟悉的,也可能因此而有些沉悶,這里先說聲道歉。· 接下來的兩部分教程會包含很有趣
7、的內容,不過我們首先需要打下良好基礎。詞法結構- 傳統(tǒng)中蘊含新意。- 源碼采用UTF-8編碼??崭癜ǎ嚎瞻祝瑃ab,換行,回車。- 標識符由字母和數字組成(外加'_'),字母和數字都是Unicode編碼。- 注釋:/* This is a comment; no nesting */ So is this. 字面值(literals)類似C語言中的字面值,但數值不需要符號以及大小標志(后續(xù)會有更多這方面內容): 230x0FF1.234e7 類似C中的字符串,但字符串是Unicode/UTF-8編碼的。同時,xNN總是有2個數字;012總是3;兩
8、個都是字節(jié): "Hello, worldn""xFF" / 1 byte"u00FF" / 1 Unicode char, 2 bytes of UTF-8 原生字符串:n.abct = "n.abct"語法概述基本上就是類C的語法,但使用反轉的類型和聲明,并使用關鍵字作為每個聲明的開頭。 var a intvar b, c *int / 注意與C的不同var d inttype S struct a, b
9、 int 基本的控制結構也十分熟悉: if a = b return true else return false for i = 0; i < 10; i+ 注意:沒有圓括號,但需要大括號。 后續(xù)會有更多有關這方面的內容。 分號分號作為語句終止符號,但:- 如果前一個符號是語句的結尾,那詞法分析程序將自動在行尾插入一個分號- 注意:比JavaScript的規(guī)則更清晰和簡單因此,下面的程序不需要分號:package mainconst three = 3var i int = threefunc main() fmt.Printf(&
10、quot;%dn", i) 在實際中,Go源碼在for和if子句之外幾乎都沒有用到分號。數值類型數值類型(numeric types)是原生內置的,也是為大家所熟知的:int uintint8 uint8 = byteint16 uint16int32 uint32
11、60; float32 complex64int64 uint64 float64 complex128還有uintptr,一個大小足夠存儲一個指針的數值。這些都是互不相同的類型;int不等于是int32,即便是在一個32位的機器上。沒有隱式類型轉換(不過不要恐慌
12、)。Bool普通的布爾類型bool,取值true和false(預定義的常量)。if語句等使用布爾表達式。指針類型和整型不是布爾類型。string原生內置的string類型代表不可改變的字節(jié)數組,即文本。string類型是用長度定界的,而不是以結尾0終止的。字符串字面值是string類型。和整型一樣不可改變??芍匦沦x值,但不能修改其值。正如"3"總是3,"hello"也總是"hello"。Go語言對字符串操作提供了良好的支持。表達式(Expressions)大多都是類C語言的操作符。二元操作符:優(yōu)先級
13、 操作符 備注5 * / % <
14、;< >> & & &是位清理操作符4 + | 是異或(xor)
15、3 = != < <= > >=2 &&1 &
16、#160; |一元操作符包括:& ! * + (外加用于通信的<-)一元操作符是求補碼/反碼操作。Go vs. C表達式可以讓C程序員驚喜的是:更少的優(yōu)先級層次(應該容易)。替代了+和不再是表達式操作符(x+是一個語句,不是表達式;*p+是(*p)+,而不是*(p+)&是新操作符,在常量表達式中很有用<<和>>等需要一個無符號的移位計數。無驚喜的是:賦值操作與所期望的一樣:+= <<= &=等表達式總體看起來相似(下標、函數調用等)例子+x23 + 3*xix <= f()a
17、 >> bf() | g()x = y + 1 && <-ch > 0x & 7 / x with the low 3 bits clearedfmt.Printf("%5.2gn", 2*math.Sin(PI/8)7.234/x + 2.3i"hello, " + "world" / concatenation
18、0; / no C-like "a" "b"數值轉型將一個數值從一個類型轉換為另一個類型稱為一次轉型,其語法形式有點類似函數調用:uint8(intVar) /截斷到相應的大小int(float64Var) /片段截斷float64(intVar) /轉為float64一些涉及string類型的轉型:string(0×1234) / = &qu
19、ot;u1234"string(sliceOfBytes) / bytes -> bytesstring(sliceOfInts) / ints -> Unicode/UTF-8byte("abc") / bytes -> bytesint("日本語") &
20、#160; / Unicode/UTF-8 -> ints切片(slice)與數組相關,稍后會有更多相關內容。常量數值常量是"理想數":沒有大小或標志,因此沒有U、L或UL作結尾。077 / 八進制0xFEEDBEEEEEEEEEEEEEEEEEEEEF /十六進制1 << 100下面是整數和浮點數值,字面值的語法決定其類型:1.234e5 / 浮點1e2 / 浮點3.2i
21、60; / 浮點虛數100 / 整數常量表達式浮點和整型常量可以任意組合,最終表達式的類型由常量的類型決定。操作自身也取決于類型。2*3.14 / 浮點: 6.283./2 / 浮點:1.53/2 / 整型:13+2i / 復數:3.0 + 2.0i/ 高精度const Ln2 = 0.693147180559
22、94530941723212145817656807const Log2E = 1/Ln2 數值的表示范圍足夠大(目前最大用1024位表示)。理想數的結果Go語言允許無需顯式轉型的情況下使用常量,前提是常量值可以被其類型表示(沒有必要進行轉型;其值表示起來沒問題):var million int = 1e6 /float語法在這里可以使用math.Sin(1)常量必須可以被其類新表示。例如:0的值為-1,不在0-255的范圍內。uint8(0) /錯誤:-1無法用uint8類型表示uint8(0)
23、160; /OKuint8(350) /錯誤:350無法用uint8類型表示uint8(35.0) /OK: 35uint8(3.5) /錯誤:3.5無法用uint8類型表示聲明聲明以一個關鍵字開頭(var, const,type和func),并且與C中的聲明次序相反:var i intconst PI = 22./7.type Point struct x, y in
24、t func sum(a, b int) int return a + b 為何要以相反次序聲明呢?早期的一個例子:var p, q *intp和q的類型都是*int。并且函數讀起來更佳,并且與其他聲明一致。還有一個原因,馬上道來。Var變量聲明以var開頭。它們可以有一個類型或一個初始化表達式;至少應有一個或二者都有。初始化表達式應該與變量匹配(還有類型!)。var i intvar j = 365.245var k int = 0var l, m uint64 = 1, 2var nanoseconds int64 = 1e9 / float64 constant!var inter, f
25、loater, stringer = 1, 2.0, "hi"分派var總是輸入var讓人生厭。我們可以通過括號讓多個變量聲明成為一組:var ( i int j = 356.245 k int = 0 l, m uint64 = 1, 2 nanoseconds int64 = 1e9 inter, floater, stringer = 1, 2.0, &q
26、uot;hi")這種形式適用于const,type, var,但不能用于func。=:"短聲明"在函數內(只有在函數內這一種情況下),下面形式的聲明: var v = value可以被縮短成: v := value(這就是另外一個名字、類型倒序的原因)類型就是值的類型(對于理想數,相應的類型是int或float64或complex128) a, b, c, d, e := 1, 2.0, "three", FOUR, 5e0i這種形式的聲明使用很頻繁,并且在諸如for循環(huán)初始化表達式中也可以使用。Const常
27、量聲明以const開頭。它們必須有一個常量表達式,可在編譯期間求值,作為初始化表達式,可以擁有一個可選的類型修飾符。const Pi = 22./7.const AccuratePi float64 = 355./113const beef, two, parsnip = "meat", 2, "veg"const ( Monday, Tuesday, Wednesday = 1, 2, 3 Thursday, Friday, Saturday = 4, 5, 6)Iota常量聲明可
28、以使用計數器:iota,每個const塊中的iota都從0開始計數,在每個隱式的分號(行尾)自增。const ( Monday = iota / 0 Tuesday = iota / 1)速記:重復上一個類型和表達式。const ( loc0, bit0 uint32 = iota, 1< loc1, bit1
29、 /1,2 loc2, bit2 /2,4)Type類型聲明以type開頭。我們后續(xù)會學習更多類型,不過先這里舉幾個例子:type Point struct x, y, z float64
30、 name stringtype Operator func(a, b int) inttype SliceOfIntPointers *int我們稍后會回到函數。New內置函數new用于分配內存。其語法類似一個函數調用,以類型作為參數,與C+中的new類似。返回一個指向已分配對象的指針。var p *Point = new(Point)v := new(int) / v的類型為*int稍后我們將看到如何構建切片(slice)Go語言中沒有用于內存釋放的delete或free。Go具備垃圾回收功能。賦值賦值是容
31、易和熟悉的:a = b但Go還支持多項賦值:x, y, z = f1(), f2(), f3()a, b = b, a /交互a,b的值函數支持多個返回值(稍后有更多細節(jié)):nbytes, error := Write(buf)控制結構與C類似,但很多地方有不同。Go支持if、for和switch。正如之前說的,無需小括號,但大括號是必要的。如果將它們看為一組,它們的用法很規(guī)律。例如,if、for和switch都支持初始化語句??刂平Y構的形式后續(xù)會有細節(jié),但總體上:if和switch語句以1元素和2元素形式呈現,后面詳細講解。for循環(huán)具有1元素和3元素的形式:1元素形式等價于C語
32、言中的while: for a 3元素形式等價于C語言中的for: for a;b;c 在所有這些形式里,任何元素都可以是空。if基本形式是大家所熟知的,但已經沒有了"else懸掛"問題了:if x < 5 less() if x < 5 less() else if x = 5 equal() 支持初始化語句;需要分號。if v := f(); v < 10 fmt.Printf("%d less than 10n", v)
33、else fmt.Printf("%d not less than 10n", v)與多元函數一起使用更有益處:if n, err = fd.Write(buf); err != nil 省略條件意為true,在這里沒有什么用。但在for,switch語句中尤其有用。for基本形式是大家所熟知的: for i := 0; i < 10; i+ 省略條件意為true: for ; fmt.Printf("looping forever") 而
34、且你還可以省略分號: for fmt.Printf("Mine! ") 不要忘記多項賦值: for i,j := 0,N; i < j; i,j = i+1,j-1 (Go中沒有像C中那樣的逗號操作符)switch細節(jié)switch與C中的switch有些類似。不過,有一些語法和語義的重要不同之處:- 表達式不必一定是常量,甚至可以不必是int。- 沒有自動的fall through- 但作為替代,語法上,最后的語句可以為fallthrough- 多case可以用
35、逗號分隔switch count%7 case 4,5,6: error() case 3: a *= v; fallthrough case 2: a *= v; fallthrough case 1: a *= v; fallthrough case 0: return a*vSwitchGo中的switch要遠比C中的強大。常見的形式:switch a case 0: f
36、mt.Printf("0") default: fmt.Printf("non-zero")switch表達式可以是任意類型,如果為空,則表示true。結果類似一個if-else鏈:a, b := xi, yjswitch case a < b: return -1 case a = b: return 0 case a > b: return 1或switch a, b := xi, yj; Br
37、eak,continue等break和continue語句的工作方式與C中的類似。它們可以指定一個label并影響外層結構:Loop: for i := 0; i < 10; i+ switch f(i) case 0, 1, 2: break Loop g(i)是的,那是一個goto。函數函數以func關鍵字開頭。如果有返回類型,返回類型放在參數的后面。return的含義和你期望的一致。func sq
38、uare(f float64) float64 return f*f 函數支持返回多個值。這樣,返回類型就是一個括號包圍的列表。func MySqrt(f float64) (float64, bool) if f >= 0 return math.Sqrt(f), true return 0, false空標識符如果你只關心MySqrt函數返回的第一個值?你仍然需要將第二個值放在一個地方。解決方法:使用空標識符_(下劃線)。它是預聲明的,可以被賦予任何無用的值。/ Don't care about bo
39、olean from MySqrt.val, _ = MySqrt(foo()在空標識符其他的適用場合中,我們仍然會展示它。帶結果變量(result variable)的函數如果你給結果參數命名了,你可以將它當作實際變量使用。func MySqrt(f float64) (v float64, ok bool) if f >= 0 v,ok = math.Sqrt(f), true else v,ok = 0,false return v,ok結果變量被初始化為"0
40、"(0,0.0,false等。根據其類型;稍后有更多有關內容)func MySqrt(f float64) (v float64, ok bool) if f >= 0 v,ok = math.Sqrt(f), true return v,ok空返回最后,一個沒有返回表達式的return將返回結果變量的當前值。下面是另外兩個MySqrt的版本:func MySqrt(f float64) (v float64, ok bool) if f >= 0 v,ok
41、= math.Sqrt(f), true return / must be explicitfunc MySqrt(f float64) (v float64, ok bool) if f < 0 return / error case return math.Sqrt(f),true0是什么Go中的內存都是被初始化了的。所有變量在執(zhí)行之前的聲明時被初始化。如果沒有顯式的初始化表達式,我們將使用對應類型的"0值"。下面的循環(huán):for i := 0; i &l
42、t; 5; i+ var v int fmt.Printf("%d ", v) v = 5將打印0 0 0 0 0。0值取決于類型:數值是0;布爾是false;空字符串是"";指針,map、切片、channel是nil;結構體是0等。Deferdefer語句負責在其所在的函數返回時執(zhí)行一個函數(或方法)。其參數在到達defer語句那個時刻被求值;其函數在返回時被執(zhí)行。func data(fileName string) string
43、 f := os.Open(fileName) defer f.Close() contents := io.ReadAll(f) return contents在關閉文件描述符、解互斥鎖等場合十分有用。每Defer執(zhí)行一個函數Go按按后入先出(LIFO)次序執(zhí)行一組defer函數。func f() for i := 0; i < 5; i+ d
44、efer fmt.Printf("%d ", i) 上面代碼將輸出4 3 2 1 0。你可以在最后關閉所有文件描述符以及解鎖所有互斥鎖。用defer跟蹤代碼func trace(s string) fmt.Println("entering:", s) func untrace(s string) fmt.Println("leaving:", s) func a() trace("a") defer un
45、trace("a") fmt.Println("in a")func b() trace("b") defer untrace("b") fmt.Println("in b") a()func main() b() 不過我們可以實現的更靈巧一些。參數當即求值,defer稍后執(zhí)行func trace(s string)
46、 string fmt.Println("entering:", s) return sfunc un(s string) fmt.Println("leaving:", s)func a() defer un(trace("a") fmt.Println("in a")func b() defer un(trace("b
47、") fmt.Println("in b") a()func main() b() 函數字面值和在C中一樣,函數不能在函數內部聲明。但函數字面值卻可以被賦值給變量。func f() for i := 0; i < 10; i+ g := func(i int) fmt.Printf("%d",i)
48、0; g(i) 函數字面值是閉包(closure)函數字面值實際上是閉包。func adder() (func(int) int) var x int return func(delta int) int x += delta return x f := adder()fmt.Print(f
49、(1)fmt.Print(f(20)fmt.Print(f(300)輸出1 21 321 f中的x累加。程序構建包(package)一個程序以一個包的形式構建,這個包還可以使用其他包提供的一些設施。一個Go程序的創(chuàng)建是通過鏈接一組包。一個包可以由多個源碼文件組成。導入包中的名字可以通過packagename.Itemname訪問。源碼文件結構每個源碼文件包括:- 一個package字句(文件歸屬于哪個包);其名字將作為導入包時的默認名字。 package fmt- 一個可選的import聲明集 import "f
50、mt" /使用默認名字 import myFmt "fmt" /使用名字myFmt- 0個或多個全局或“包級別”聲明。單一文件包package main / 這個文件是包main的一部分import "fmt" / 這個文件使用了包"fmt"const hello = "Hello, 世界n"func main() fmt.Print(hello)main和main.main每個Go程序包含一個名為main的包以及其ma
51、in函數,在初始化后,程序從main開始執(zhí)行。類似C,C+中的main()函數。main.main函數沒有參數,沒有返回值。當main.main返回時,程序立即退出并返回成功。os包os包提供Exit函數以及訪問文件I/O以及命令行參數的函數等。/ A version of echo(1)package mainimport ( "fmt" "os")func main() if len(os.Args) < 2 / length of a
52、rgument slice os.Exit(1) for i := 1; i < len(os.Args); i+ fmt.Printf("arg %d: %sn", i, os.Argsi) / falling off end = os.Exit(0)全局作用域與包作用域在一個包中,所有全局變量、函數、類型以及
53、常量對這個包的所有代碼可見。對于導入該包的包而言,只有以大寫字母開頭的名字是可見的:全局變量、函數、類型、常量以及方法和結構體中全局類型以及變量的字段。const hello = "you smell" / 包內可見const Hello = "you smell nice" /全局可見const _Bye = "stinko!" / _不是大寫字母這與C/C+非常不同:沒有extern、static、privat
54、e以及public。初始化有兩種方法可以在main.main執(zhí)行前初始化全局變量:1) 帶有初始化語句的全局聲明2) 在init函數內部,每個源文件中都可能有init函數。包依賴可以保證正確的執(zhí)行順序。初始化總是單線程的。初始化例子package transcendentalimport "math"var Pi float64func init() Pi = 4*math.Atan(1) / init function computes Pi=package mainimport ( "f
55、mt" "transcendental")var twoPi = 2*transcendental.Pi / decl computes twoPifunc main() fmt.Printf("2*Pi = %gn", twoPi)=輸出: 2*Pi = 6.283185307179586包與程序構建要構建一個程序,包以及其中的文件必須按正確的次序進行編譯。包依賴關系決定了按何種次序構建包。在一個包內部,源文件必須一起被編譯。包作為一個單元被編譯,按慣例,每個目錄包含一
56、個包,忽略測試,cd mypackage6g *.go通常,我們使用make; Go語言專用工具即將發(fā)布(譯注:Go 1中可直接使用go build、go install等高級命令,可不再直接用6g、6l等命令了。)構建fmt包% pwd/Users/r/go/src/pkg/fmt% lsMakefile fmt_test.go format.go print.go # % make # hand-written but trivial% lsMakefile _go_.6 _obj fmt_test.go format.go print.go # % make clean; make目標文
57、件被放在_obj子目錄中。編寫Makefiles時通常使用Make.pkg提供的幫助。看源碼。測試要測試一個包,可在這個包內編寫一組Go源文件;給這些文件命名為*_test.go。在這些文件內,名字以Testa-z開頭的全局函數會被測試工具gotest自動執(zhí)行,這些函數應使用下面函數簽名:func TestXxx(t *testing.T)testing包提供日志、benchmarking、錯誤報告等支持。一個測試例子摘自fmt_test.go中的一段有趣代碼:import ( "testing")func TestFlagParser(
58、t *testing.T) var flagprinter flagPrinter for i := 0; i < len(flagtests); i+ tt := flagtestsi s := Sprintf(tt.in, &flagprinter) i
59、f s != tt.out / method call coming up obvious syntax. t.Errorf("Sprintf(%q, &flagprinter) => %q,"+" want %q", tt.in, s, tt.out) &
60、#160; gotest(譯注:在go 1中gotest工具用go test命令替代)% lsMakefile fmt.a fmt_test.go format.go print.go # % gotest # by default, does all *_test.goPASSwally=% gotest -v fmt_test.go= RUN fmt.TestFlagParser PASS: fmt.TestFlagParser (0.00 seconds)= RUN fmt.TestArrayPrint
61、er PASS: fmt.TestArrayPrinter (0.00 seconds)= RUN fmt.TestFmtInterface PASS: fmt.TestFmtInterface (0.00 seconds)= RUN fmt.TestStructPrinter PASS: fmt.TestStructPrinter (0.00 seconds)= RUN fmt.TestSprintf PASS: fmt.TestSprintf (0.00 seconds) # plus lots morePASS%一個benchmark的測試例子Benchmark的函數簽名如下:func
62、BenchmarkXxxx(b *testing.B)并被循環(huán)執(zhí)行b.N次;其余的由testing包完成。下面是一個來自fmt_test.go中的benchmark例子:package fmt / package is fmt, not mainimport ( "testing")func BenchmarkSprintfInt(b *testing.B) for i := 0; i < b.N; i+ Sprintf
63、("%d", 5) Benchmarking: gotest% gotest -bench="." # regular expression identifies whichfmt_test.BenchmarkSprintfEmpty 5000000310 ns/opfmt_test.BenchmarkSprintfString 2000000774 ns/opfmt_test.BenchmarkSprintfInt5000000663 ns/opfmt_test.BenchmarkSprintfIntInt 2000
64、000969 ns/op%庫庫就是包。目前的庫規(guī)模是適中的,但還在增長。一些例子:包 目的 例子fmt 格式化I/O
65、160; Printf、Scanfos OS接口 Open, Read, Writestrconv numbers<->
66、 strings Atoi, Atof, Itoaio 通用I/O Copy, Pipeflag flags: help等 Bool
67、, Stringlog 事件日志 Logger, Printfregexp 正則表達式 Compile, M
68、atchtemplate html等 Parse, Executebytes 字節(jié)數組 Compare, Buffer更
69、多關于fmtfmt包包含一些熟悉的名字:Printf 打印到標準輸出Sprintf 返回一個字符串Fprintf 寫到os.Stderr等還有Print, Sprint, Fprint 無格式no formatPrintln, Sprintln, Fprintln 無格式,但中間加入空格,結尾加入nfmt.Printf("%d %d %gn", 1, 2, 3.5)fmt.Print(1, " ", 2, " ", 3.5, "n")fmt.Println(1, 2, 3.5)每個都輸出相同的結果:"1
70、2 3.5n"庫文檔源碼中包含注釋。命令行或web工具可以將注釋提取出來。鏈接:/pkg/命令: % godoc fmt % godoc fmt PrintfGo程序設計語言(二)本文譯自Rob Pike的Go語言PPT教程 "The Go Programming Language Part 2(updated June 2011)"。由于該教程的最新更新時間早于Go 1版本發(fā)布,因此該PPT中的一些內容與Go 1語言規(guī)范略有差異,到時我會在相應的地方做上注解。
71、第二部分大綱· 復合類型 結構體、數組、切片、Maps· 方法 不再只是為結構體· 接口數組數組Go中的數組與C語言中的數組差異很大,倒更類似Pascal中的數組。 (Slice,下個話題,有些像C語言中的數組)var ar 3int聲明ar為一個擁有三個整型數的數組,所有元素初始化為0。大小是類型的一個組成部分。內置的函數len可以用于獲取數組大?。簂en(ar) = 3數組是值類型Go中的數組是值,而非C語言中的隱式指針。你可以獲得數組的地址,并生成一個指向數組的指針(例如,將其高效地傳遞給函數): func f(a 3int) fmt.Printl
72、n(a) func fp(a *3int) fmt.Println(a) func main() var ar 3 int f(ar) / 傳遞一個ar的拷貝 fp(&ar) / 傳遞一個指向ar的指針 輸出結果:0 0 0&0 0 0數組字面值所有的符合類型都有相同的值創(chuàng)建語法。以數組為例,其語法如下: 3個整數的數組: 3int1, 2, 3 10個整數的數組,前三個元素不是0: 10int 1, 2
73、, 3 不想數?使用代表長度: .int1, 2, 3 不想初始化所有值?使用key:value對: 10int2:1, 3:1, 5:1, 7:1 指向數組字面值的指針你可以獲取數組字面值的地址,這樣可以得到一個指向新建數組實例的指針: func fp(a *3int) fmt.Println(a) func main() for i := 0; i < 3; i+ fp(&3inti, i*i, i*i*i)&
74、#160; 輸出結果: &0 0 0&1 1 1&2 4 8 切片(Slice)切片切片是對數組中某一段的引用。 切片比普通數組應用得更多也更廣泛。 切片使用的代價很低。 一個切片類型很像一個沒有大小的數組類型: var a int 內置的len(a)可以返回切片中元素的個數。 通過對數組或切片進行"切片",我們可以創(chuàng)建一個新切片: a = ar7:9 a(上面例子中的a)的有效下標值是0和1;len(a) = 2。 切片速記當對數組進行切片時,第一個下標值默認是0: ar:n等價于a0:n。 第二個下標值默認為len(array/slice): arn:等價于arn:len(ar)。 因此由數組創(chuàng)建切片時: ar:等價于ar0:len(ar)。 切片引用數組概念上: type Slice struct base *elemType / 指向0th元素的指針 len int / 切片中元素的數量
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 科技園區(qū)廠房租賃合同模板
- 涪陵區(qū)易燃品運輸合同模板
- 星巴克采購合同模板
- 出租鋼管衣柜合同模板
- 借條合同模板 個人簽字
- 文件授權合同模板
- 通訊電纜維修合同模板
- 樓梯彩涂板采購合同模板
- 設備配件銷售合同模板
- 2024年天津客運資格證要考幾科
- 火鍋供料合同
- 2023年湖南長沙黃花國際機場分公司招聘考試真題
- 工資表簡易模板
- 小學三年級數獨比賽“六宮”練習題(88道)
- 《憲法宣傳教育》班會
- 農村積分超市實施方案(2篇)
- PICC維護流程及常見并發(fā)癥的處理成品
- 人教版高中英語必修一年級上冊冊單元訓練題 全冊
- 專業(yè)課程說課省公開課金獎全國賽課一等獎微課獲獎課件
- 《SketchUp三維輔助設計》課件-02 SketchUp的繪圖環(huán)境
- 《傳播學教程》教學大綱
評論
0/150
提交評論