Go語言程序基本結構以下:
A、包聲明
B、引入包
C、函數
D、變量
E、語句 & 表達式
F、註釋編程
package main //包聲明 import "fmt" //引入包 func main(){ //main函數 //打印Hello World fmt.Print("Hello World!") }
Go語言程序由多個標記組成,能夠是關鍵字、標識符、常量、字符串、符號。
fmt.Println("Hello, World!")語句由6個標記組成:數組
fmt . Println ( "Hello, World!" )
在Go語言程序中,一行表明一個語句結束。每一個語句不須要像C家族中的其它語言同樣以分號;結尾。
若是打算將多個語句寫在同一行,則必須使用;人爲區分,但在實際開發中不推薦。閉包
fmt.Println("Hello, World!") fmt.Println("Hello, Go!")
註釋不會被編譯,每個包應該有相關注釋。
單行註釋是最多見的註釋形式,能夠在任何地方使用以 // 開頭的單行註釋。 多行註釋也叫塊註釋,均已以 / 開頭,並以 / 結尾。 app
//打印hello world /* It print to console a string */
標識符用來命名變量、類型等程序實體。標識符是由一個或是多個字母(A~Z和a~z)數字(0~9)、下劃線_組成的序列,但第一個字符必須是字母或下劃線而不能是數字。無效的標識符以下:
1ab(以數字開頭)
case(Go語言的關鍵字)
a+b(運算符是不容許的)編程語言
Go語言有25個關鍵字或保留字:break,case,chan,const,continue,default,defer,else,fallthrough,for,func,go,goto,if,import,interface,map,package,range,return,select,struct,switch,type,var
Go語言有36個預約義標識符:append,bool,byte,cap,close,complex,complex64,complex128,copy,false,float32,float64,imag,int,int8,int16,int32,int64,iota,len,make,new,nil,panic,uint,uint8,uint16,uint32,uint64,uintptr,print,println,real,recover,string,true
程序通常由關鍵字、常量、變量、運算符、類型和函數組成。
程序中可能會使用到分隔符:括號 (),中括號 [] 和大括號 {}。
程序中可能會使用到標點符號:.、,、;、: 和 …。ide
Go語言中變量的聲明必須使用空格隔開,如:var age int;
語句中適當使用空格能讓程序看易閱讀。
無空格:fruit=apples+oranges;
在變量與運算符間加入空格,程序看起來更加美觀,如:fruit = apples + oranges;
函數
Go語言中,使用大小寫來決定常量、變量、類型、接口、結構或函數是否能夠被外部包所調用。
函數名首字母小寫即爲private : func getId() {}
函數名首字母大寫即爲public : func Printf() {}
佈局
Go語言程序經過package來組織,只有package名稱爲main的包能夠包含main函數。
一個可執行程序有且僅有一個main包。
經過import關鍵字來導入其餘非main包。
能夠經過import關鍵字單個導入: post
import "fmt" import "io"
也能夠同時導入多個: 測試
import { "fmt", "io"}
或是:
import ( "fmt" )
使用<PackageName>.<FunctionName>
調用:
package別名:import fmt2 "fmt"
爲fmt起別名爲fmt2
省略調用:調用的時候只須要Println(),而不須要fmt.Println()import . "fmt"
前面加個點表示省略調用,那麼調用該模塊裏面的函數,能夠不用寫模塊名稱:
import . "fmt" func main (){ Println("hello,world")}
在Go編程語言中,數據類型用於聲明函數和變量。
數據類型是爲了把數據分紅所需內存大小不一樣的數據,編程的時候須要用大數據的時候才須要申請大內存,就能夠充分利用內存。
布爾型的值只能夠是常量true或者false。var b bool = true
整型int和浮點型float32float64,Go語言支持整型和浮點型數字,而且原生支持複數,其中位的運算採用補碼。
uint8:無符號8位整型(0到255)
uint16:無符號16位整型(0到65535)
uint32:無符號32位整型(0到4294967295)
uint64:無符號64位整型(0到18446744073709551615)
int8:有符號8位整型(-128到127)
int16:有符號16位整型(-32768到32767)
int32:有符號32位整型(-2147483648到2147483647)
int64:有符號64位整型(-9223372036854775808到 9223372036854775807)
float32:IEEE-754 32位浮點型數
float64:IEEE-754 64位浮點型數
complex64:32位實數和虛數
complex128:64位實數和虛數
byte:相似uint8
rune:相似int32
uint:32或64位
int:與uint同樣大小
uintptr:無符號整型,用於存放一個指針
字符串就是一串固定長度的字符鏈接起來的字符序列。Go語言的字符串是由單個字節鏈接起來的。Go語言的字符串的字節使用UTF-8編碼標識Unicode文本。
派生類型包括:
A、指針類型(Pointer)
B、數組類型
C、結構化類型(struct)
D、Channel 類型
E、函數類型
F、切片類型
G、接口類型(interface)
H、Map 類型
變量是計算機語言中能儲存計算結果或能表示值的抽象概念。變量能夠經過變量名訪問。
Go 語言變量名由字母、數字、下劃線組成,其中首個字母不能爲數字。
聲明變量的通常形式使用var關鍵字:var identifier type
第一種,指定變量類型,聲明後若不賦值,使用默認值。
var v_name v_type v_name = value
第二種,根據值自行斷定變量類型。var v_name = value
第三種,省略var, 注意 :=左側的變量不該該是已經聲明過的,不然會致使編譯錯誤。
v_name := value // 例如 var a int = 10 var b = 10 c := 10
//類型相同多個變量, 非全局變量 var vname1, vname2, vname3 type vname1, vname2, vname3 = v1, v2, v3 //不須要顯示聲明類型,自動推斷 var vname1, vname2, vname3 = v1, v2, v3 //出如今:=左側的變量不該該是已經被聲明過的,不然會致使編譯錯誤 vname1, vname2, vname3 := v1, v2, v3 //分解關鍵字的寫法通常用於聲明全局變量 var ( vname1 v_type1 vname2 v_type2 )
實例:
var x, y int var ( a int b bool ) var c, d int = 1, 2 var e, f = 123, "hello" //不帶聲明格式的只能在函數體中出現 //g, h := 123, "hello"
int、float、bool、string等基本類型都屬於值類型,值類型的變量直接指向存在內存中的值。
當使用等號=將一個變量的值賦值給另外一個變量時,如:j = i,其實是在內存中將i的值進行拷貝。
能夠經過&i來獲取變量i的內存地址,例如0xf840000040(地址隨機)。值類型的變量的值存儲在棧中。
內存地址會根據機器的不一樣而有所不一樣,相同的程序在不一樣的機器上執行後也會有不一樣的內存地址。由於每臺機器可能有不一樣的存儲器佈局,而且位置分配也可能不一樣。
更復雜的數據一般會須要使用多個字,通常使用引用類型保存。
一個引用類型的變量r1存儲的是r1的值所在的內存地址(數字),或內存地址中第一個字所在的位置。
同一個引用類型的指針指向的多個字能夠是在連續的內存地址中(內存佈局是連續的),也能夠將這些字分散存放在內存中,每一個字都指示了下一個字所在的內存地址。
當使用賦值語句r2 = r1時,只有引用(地址)被複制。
若是r1的值被改變,r1的全部引用都會指向被修改後的內容。
做用域爲已聲明標識符所表示的常量、類型、變量、函數或包在源代碼中的做用範圍。
Go語言中變量能夠在三個地方聲明:
A、函數內定義的變量稱爲局部變量
B、函數外定義的變量稱爲全局變量
C、函數定義中的變量稱爲形式參數
在函數體內聲明的變量爲局部變量,其做用域只在函數體內,參數和返回值變量也是局部變量。
package main import "fmt" func main() { /* 聲明局部變量 */ var a, b, c int /* 初始化參數 */ a = 10 b = 20 c = a + b fmt.Printf ("結果: a = %d, b = %d and c = %d\n", a, b, c) }
在函數體外聲明的變量爲全局變量,全局變量能夠在整個包甚至外部包(被導出後)使用。
package main import "fmt" /* 聲明全局變量 */ var g int func main() { /* 聲明局部變量 */ var a, b int /* 初始化參數 */ a = 10 b = 20 g = a + b fmt.Printf("結果: a = %d, b = %d and g = %d\n", a, b, g) }
Go語言程序中全局變量與局部變量名稱能夠相同,可是函數內的局部變量會被優先考慮。
package main import "fmt" /* 聲明全局變量 */ var g int = 20 func main() { /* 聲明局部變量 */ var g int = 10 fmt.Printf ("結果: g = %d\n", g) }
形式參數會做爲函數的局部變量來使用。
package main import "fmt" /* 聲明全局變量 */ var a int = 20; func main() { /* main 函數中聲明局部變量 */ var a int = 10 var b int = 20 var c int = 0 fmt.Printf("main()函數中 a = %d\n", a); c = sum( a, b); fmt.Printf("main()函數中 c = %d\n", c); } /* 函數定義-兩數相加 */ func sum(a, b int) int { fmt.Printf("sum() 函數中 a = %d\n", a); fmt.Printf("sum() 函數中 b = %d\n", b); return a + b; }
不一樣類型的局部和全局變量默認值爲:
int 0
float32 0
pointer nil
常量是一個簡單值的標識符,在程序運行時,不會被修改的量。
常量中的數據類型只能夠是布爾型、數字型(整數型、浮點型和複數)和字符串型。
常量的定義格式:const identifier [type] = value
能夠省略類型說明符[type],由於編譯器能夠根據變量的值來推斷其類型。
顯式類型定義: const b string = "abc"
隱式類型定義: const b = "abc"
多個相同類型的聲明能夠簡寫爲:const c_name1, c_name2 = value1, value2
常量使用實例:
package main import "fmt" func main() { const LENGTH int = 10 const WIDTH int = 5 var area int const a, b, c = 1, false, "str" //多重賦值 area = LENGTH * WIDTH fmt.Printf("面積爲 : %d", area) println() println(a, b, c) }
常量能夠用做枚舉:
const ( Unknown = 0 Female = 1 Male = 2)
數字 0、1和2分別表明未知性別、女性和男性。
常量能夠用len(), cap(), unsafe.Sizeof()函數計算表達式的值。常量表達式中,函數必須是內置函數。
package main import "unsafe" const ( a = "abc" b = len(a) c = unsafe.Sizeof(a) ) func main(){ println(a, b, c) }
Iota是一個特殊常量,是一個能夠被編譯器修改的常量。
在每個const關鍵字出現時,被重置爲0,而後再下一個const出現以前,每出現一次iota,其所表明的數字會自動增長1。
iota能夠被用做枚舉值:
const ( a = iota b = iota c = iota )
第一個iota等於0,每當iota在新的一行被使用時,值都會自動加1,因此a=0, b=1, c=2能夠簡寫爲以下形式:
const ( a = iota b c )
使用實例:
package main import "fmt" func main() { const ( a = iota //0 b //1 c //2 d = "ha" //獨立值,iota += 1 e //"ha" iota += 1 f = 100 //iota +=1 g //100 iota +=1 h = iota //7,恢復計數 i //8 ) fmt.Println(a,b,c,d,e,f,g,h,i) }
存儲數據的Byte、KB、MB、GB、TB、PB的計算:
const( b=1<<(10*iota) kb mb gb tb pb ) func dataByte() { fmt.Println("b=",b) fmt.Println("kb=",kb) fmt.Println("mb=",mb) fmt.Println("gb=",gb) fmt.Println("tb=",tb) fmt.Println("pb=",pb) }
運算符用於在程序運行時執行數學或邏輯運算。Go語言內置的運算符有:
A、算術運算符
B、關係運算符
C、邏輯運算符
D、位運算符
E、賦值運算符
F、其它運算符
+ 相加 A+B - 相減 A-B * 相乘 A*B / 相除 A/B % 求餘 A%B ++ 自增 A++ -- 自減 A--
算術運算實例:
package main import "fmt" func main() { var a int = 21 var b int = 10 var c int c = a + b fmt.Printf("相加 - c 的值爲 %d\n", c) c = a - b fmt.Printf("相減 - c 的值爲 %d\n", c) c = a * b fmt.Printf("相乘 - c 的值爲 %d\n", c) c = a / b fmt.Printf("相除 - c 的值爲 %d\n", c) c = a % b fmt.Printf("求餘 - c 的值爲 %d\n", c) a++ fmt.Printf("自增 - a 的值爲 %d\n", a) a-- fmt.Printf("自減 - a 的值爲 %d\n", a) }
==:檢查兩個值是否相等,若是相等返回 True 不然返回 False。 !=:檢查兩個值是否不相等,若是不相等返回 True 不然返回 False。 >:檢查左邊值是否大於右邊值,若是是返回 True 不然返回 False。 <:檢查左邊值是否小於右邊值,若是是返回 True 不然返回 False。 >=:檢查左邊值是否大於等於右邊值,若是是返回 True 不然返回 False。 <=:檢查左邊值是否小於等於右邊值,若是是返回 True 不然返回 False。
&&:邏輯AND運算符。 若是兩邊的操做數都是True,則條件True,不然爲False。 ||:邏輯OR運算符。 若是兩邊的操做數有一個True,則條件True,不然爲False。 !:邏輯NOT運算符。 若是條件爲True,則邏輯NOT條件False,不然爲True。
&:按位與運算符"&"是雙目運算符,功能是參與運算的兩數各對應的二進位進行相與。 |:按位或運算符"|"是雙目運算符,功能是參與運算的兩數各對應的二進位進行相或。 ^:按位異或運算符"^"是雙目運算符,功能是參與運算的兩數各對應的二進位進行相異或,當兩對應的二進位相異時,結果爲1。 <<:左移運算符"<<"是雙目運算符,左移n位就是乘以2的n次方,功能把"<<"左邊的運算數的各二進位所有左移若干位,由"<<"右邊的數指定移動的位數,高位丟棄,低位補0。 >>:右移運算符">>"是雙目運算符,右移n位就是除以2的n次方,功能是把">>"左邊的運算數的各二進位所有右移若干位,">>"右邊的數指定移動的位數。
位運算實例:
package main import "fmt" func main() { var a uint = 60 /* 60 = 0011 1100 */ var b uint = 13 /* 13 = 0000 1101 */ var c uint = 0 c = a & b /* 12 = 0000 1100 */ fmt.Printf("& - c 的值爲 %d\n", c ) c = a | b /* 61 = 0011 1101 */ fmt.Printf("| - c 的值爲 %d\n", c ) c = a ^ b /* 49 = 0011 0001 */ fmt.Printf("^ - c 的值爲 %d\n", c ) c = a << 2 /* 240 = 1111 0000 */ fmt.Printf("<< - c 的值爲 %d\n", c ) c = a >> 2 /* 15 = 0000 1111 */ fmt.Printf(">> - c 的值爲 %d\n", c ) }
=:簡單的賦值運算符,將一個表達式的值賦給一個左值 +=:相加後再賦值 -=:相減後再賦值 *=:相乘後再賦值 /=:相除後再賦值 %=:求餘後再賦值 <<=:左移後賦值 >>=:右移後賦值 &=:右移後賦值 ^=:按位異或後賦值 |=:按位或後賦值
賦值運算符實例:
package main import "fmt" func main() { var a int = 21 var c int c = a fmt.Printf("= 運算符實例,c 值爲 = %d\n", c ) c += a fmt.Printf("+= 運算符實例,c 值爲 = %d\n", c ) c -= a fmt.Printf("-= 運算符實例,c 值爲 = %d\n", c ) c *= a fmt.Printf("*= 運算符實例,c 值爲 = %d\n", c ) c /= a fmt.Printf("/= 運算符實例,c 值爲 = %d\n", c ) c = 200; c <<= 2 fmt.Printf("<<= 運算符實例,c 值爲 = %d\n", c ) c >>= 2 fmt.Printf(">>= 運算符實例,c 值爲 = %d\n", c ) c &= 2 fmt.Printf("&= 運算符實例,c 值爲 = %d\n", c ) c ^= 2 fmt.Printf("^= 運算符實例,c 值爲 = %d\n", c ) c |= 2 fmt.Printf("|= 運算符實例,c 值爲 = %d\n", c ) }
&:返回變量存儲地址 *:指針變量
實例:
package main import "fmt" func main() { var a int = 4 var b int32 var c float32 var ptr *int /* 運算符實例 */ fmt.Printf("a 變量類型爲 = %T\n", a ) fmt.Printf("b 變量類型爲 = %T\n", b ) fmt.Printf("c 變量類型爲 = %T\n", c ) fmt.Printf("ptr變量類型爲 = %T\n", ptr) /* & 和 * 運算符實例 */ ptr = &a /* 'ptr' 包含了 'a' 變量的地址 */ fmt.Printf("a 的值爲 %d\n", a); fmt.Printf("*ptr 爲 %d\n", *ptr); }
有些運算符擁有較高的優先級,二元運算符的運算方向均是從左至右。
優先級 運算符
7 ^、! 6 * 、/、%、 <<、>>、&、^ 5 +、-、|、^ 4 ==、!=、<、<=、>=、> 3 <、- 2 && 1 ||
運算符優先級實例:
package main import "fmt" func main() { var a int = 20 var b int = 10 var c int = 15 var d int = 5 var e int e = (a + b) * c / d // ( 30 * 15 ) / 5 fmt.Printf("(a + b) * c / d 的值爲 : %d\n", e) e = ((a + b) * c) / d // (30 * 15 ) / 5 fmt.Printf("((a + b) * c) / d 的值爲 : %d\n", e) e = (a + b) * (c / d) // (30) * (15/5) fmt.Printf("(a + b) * (c / d) 的值爲 : %d\n", e) e = a + (b*c)/d // 20 + (150/5) fmt.Printf("a + (b * c) / d 的值爲 : %d\n", e) }
條件語句須要開發者經過指定一個或多個條件,並經過測試條件是否爲 true來決定是否執行指定語句,並在條件爲false的狀況在執行另外的語句。
條件語句的結構以下:
if語句由一個布爾表達式後緊跟一個或多個語句組成。
Go編程語言中if語句的語法以下:
if 布爾表達式 { /* 在布爾表達式爲 true 時執行 */}
If在布爾表達式爲true時,其後緊跟的語句塊執行,若是爲false則不執行。
if語句後可使用可選的else語句, else語句中的表達式在布爾表達式爲 false時執行。
Go編程語言中 if...else 語句的語法以下:
if 布爾表達式 { /* 在布爾表達式爲 true 時執行 */} else { /* 在布爾表達式爲 false 時執行 */}
If在布爾表達式爲true時,其後緊跟的語句塊執行,若是爲false則執行 else語句塊。
package main import "fmt" func main() { var a int = 100 var b int = 0 if a > b { println("a > b") } else { fmt.Println("a < b") } }
if或else if語句中嵌入一個或多個if或else if語句。
switch語句用於基於不一樣條件執行不一樣動做,每個case分支都是惟一的,從上直下逐一測試,直到匹配爲止。
switch語句執行的過程從上至下,直到找到匹配項,匹配項後面也不須要再加break。
Go編程語言中switch語句的語法以下:
switch var1 { case val1: ... case val2: ... default: ...}
變量var1能夠是任何類型,而val1和val2則能夠是同類型的任意值。類型不被侷限於常量或整數,但必須是相同的類型;或者最終結果爲相同類型的表達式。能夠同時測試多個可能符合條件的值,使用逗號分割它們,例如:case val1, val2, val3。
switch流程結構以下:
Switch實例以下:
package main import "fmt" func grade(score int)string{ var grade string; switch{ case score<0 && score > 100: fmt.Printf("score is error") grade = "Error" case score < 60: fmt.Printf("F") grade = "F" case score<80: fmt.Printf("C") grade = "C" case score<90: fmt.Printf("B") grade = "B" case score<=100: fmt.Printf("A") grade = "A" } return grade } func operator(a,b int, op string)int{ var result int switch op { case "+": result = a + b case "-": result = a -b case "*": result = a * b case "/": result = a / b default: panic("unsupported operator:" + op) } return result } func main() { grade(100) fmt.Println(operator(3,6,"+")) }
switch語句會自動break,不用每一個case分支都break,若是要取消break,可使用fallthrough。Switch後能夠不帶表達式。
switch語句還能夠被用於type-switch來判斷某個interface變量中實際存儲的變量類型。
Type Switch語法格式以下:
switch x.(type){ case type: statement(s); case type: statement(s); /* 能夠定義任意個數的case */ default: /* 可選 */ statement(s); }
實例:
var x interface{} switch i := x.(type) { case nil: fmt.Printf(" x 的類型 :%T",i) case int: fmt.Printf("x 是 int 型") case float64: fmt.Printf("x 是 float64 型") case func(int) float64: fmt.Printf("x 是 func(int) 型") case bool, string: fmt.Printf("x 是 bool 或 string 型" ) default: fmt.Printf("未知型") }
select是Go中的一個控制結構,相似於用於通訊的switch語句。每一個case必須是一個通訊操做,要麼是發送要麼是接收。
select隨機執行一個可運行的case。若是沒有case可運行,它將阻塞,直到有case可運行。一個默認的子句應該老是可運行的。
Go編程語言中select語句的語法以下:
select { case communication clause: statement(s); case communication clause: statement(s); /* 能夠定義任意數量的 case */ default: /* 可選 */ statement(s); }
select語句中:
A、每一個case都必須是一個通訊
B、全部channel表達式都會被求值,
C、全部被髮送的表達式都會被求值,若是任意某個通訊能夠進行,它就執行;其餘被忽略。
D、若是有多個case均可以運行,Select會隨機公平地選出一個執行。其餘不會執行。
不然:
若是有default子句,則執行該語句。
若是沒有default字句,select將阻塞,直到某個通訊能夠運行;Go不會從新對channel或值進行求值。
func main() { var c1, c2, c3 chan int var i1, i2 int select { case i1 = <-c1: fmt.Printf("received ", i1, " from c1\n") case c2 <- i2: fmt.Printf("sent ", i2, " to c2\n") case i3, ok := (<-c3): // same as: i3, ok := <-c3 if ok { fmt.Printf("received ", i3, " from c3\n") } else { fmt.Printf("c3 is closed\n") } default: fmt.Printf("no communication\n") } }
實際問題中有許多具備規律性的重複操做,所以在程序中就須要重複執行某些語句。
循環語句的結構以下:
for循環是一個循環控制結構,能夠執行指定次數的循環。
G語言的for循環有3種形式,只有其中的一種使用分號。
for init; condition; post { } for condition { } for { }
init:通常爲賦值表達式,給控制變量賦初值;
condition:關係表達式或邏輯表達式,循環控制條件;
post:通常爲賦值表達式,給控制變量增量或減量。
for語句執行過程以下:
A、先對錶達式init賦初值;
B、判別賦值表達式init是否知足給定條件,若其值爲真,知足循環條件,則執行循環體內語句,而後執行post,進入第二次循環,再判別condition;不然判斷condition的值爲假,不知足條件,就終止for循環,執行循環體外語句。
for循環的range格式能夠對 slice、map、數組、字符串等進行迭代循環。格式以下:
for key, value := range oldMap { newMap[key] = value}
for語句的流程結構以下:
實例以下:
package main import "fmt" func main() { var b int = 15 var a int numbers := [6]int{1, 2, 3, 5} /* for 循環 */ for a := 0; a < 10; a++ { fmt.Printf("a 的值爲: %d\n", a) } for a < b { a++ fmt.Printf("a 的值爲: %d\n", a) } for i,x:= range numbers { fmt.Printf("第 %d 位 x 的值 = %d\n", i,x) } }
Go語言容許用戶在循環內使用循環。Go語言嵌套循環的格式:
for [condition | ( init; condition; increment ) | Range]{ for [condition | ( init; condition; increment ) | Range] { statement(s); } statement(s);}
循環嵌套實例:
package main import "fmt" func main() { /* 定義局部變量 */ var i, j int for i=2; i < 100; i++ { for j=2; j <= (i/j); j++ { if(i%j==0) { break; // 若是發現因子,則不是素數 } } if(j > (i/j)) { fmt.Printf("%d 是素數\n", i); } } }
循環控制語句能夠控制循環體內語句的執行過程。GO語言支持如下三種循環控制語句:
A、break語句
常常用於中斷當前for循環或跳出switch語句。
用於循環語句中跳出循環,並開始執行循環後的語句。
break在switch(開關語句)中在執行一條case後跳出語句的做用。
break 語法格式以下:break;
break語句流程結果以下:
/* 定義局部變量 */ var a int = 10 /* for 循環 */ for a < 20 { fmt.Printf("a 的值爲 : %d\n", a); a++; if a > 15 { /* 使用 break 語句跳出循環 */ break; } }
B、continue語句
Go語言的continue語句用於跳過當前循環執行下一次循環語句。
for循環中,執行continue語句會觸發for增量語句的執行。
continue語法格式以下:continue;
Continue語句流程結構以下:
/* 定義局部變量 */ var a int = 10 /* for 循環 */ for a < 20 { if a == 15 { /* 跳過這次循環 */ a = a + 1; continue; } fmt.Printf("a 的值爲 : %d\n", a); a++; }
C、goto語句
Go語言的goto語句能夠無條件地轉移到過程當中指定的行。
goto語句一般與條件語句配合使用。可用來實現條件轉移,構成循環,跳出循環體等功能。
在結構化程序設計中通常不主張使用goto語句,以避免形成程序流程的混亂,使理解和調試程序都產生困難。
goto語法格式以下:
goto label; ... label: statement;
goto語句流程結構以下:
/* 定義局部變量 */ var a int = 10 /* 循環 */ LOOP: for a < 20 { if a == 15 { /* 跳過迭代 */ a = a + 1 goto LOOP } fmt.Printf("a的值爲 : %d\n", a) a++ }
若是循環中條件語句永遠不爲false,則會進行無限循環。能夠經過for循環語句中只設置一個條件表達式來實現無限循環。
for true{ fmt.Printf("這是無限循環。\n"); }
函數是基本的代碼塊,用於執行一個任務。
Go語言最少有個main()函數。
能夠經過函數來劃分不一樣功能,邏輯上每一個函數執行的是指定的任務。
函數聲明告訴編譯器函數的名稱、返回類型和參數。
Go語言標準庫提供了多種可用的內置的函數。例如,len()函數能夠接受不一樣類型參數並返回該類型的長度。若是傳入的是字符串則返回字符串的長度,若是傳入的是數組,則返回數組中包含的元素個數。
Go 語言函數定義格式以下:
func function_name( [parameter list] ) [return_types] { 函數體}
函數定義解析:
func:函數由func開始聲明
function_name:函數名稱,函數名和參數列表一塊兒構成了函數簽名。
parameter list:參數列表,參數就像一個佔位符,當函數被調用時,能夠將值傳遞給參數,傳遞的值被稱爲實際參數。參數列表指定的是參數類型、順序、及參數個數。參數是可選的,函數能夠不包含參數。
return_types:返回類型,函數返回一列值。return_types是返回值的數據類型。有些功能不須要返回值,return_types不是必須的。
函數體:函數定義的代碼集合。
函數實例以下:
/* 函數返回兩個數的最大值 */ func max(num1, num2 int) int { /* 聲明局部變量 */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
當建立函數時,定義函數須要作什麼,經過調用該函數來執行指定任務。
調用函數,向函數傳遞參數,並返回值,例如:
package main import "fmt" func main() { /* 定義局部變量 */ var a int = 100 var b int = 200 var ret int /* 調用函數並返回最大值 */ ret = max(a, b) fmt.Printf( "最大值是 : %d\n", ret ) } /* 函數返回兩個數的最大值 */ func max(num1, num2 int) int { /* 定義局部變量 */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
Go語言函數能夠返回多個值。
package main import "fmt" func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("Mahesh", "Kumar") fmt.Println(a, b) }
函數若是使用參數,參數變量稱爲函數的形參。
調用函數,能夠經過兩種方式來傳遞參數:
A、值傳遞
值傳遞是指在調用函數時將實際參數複製一份傳遞到函數中,在函數中若是對參數進行修改,將不會影響到實際參數。
B、引用傳遞
引用傳遞是指在調用函數時將實際參數的地址傳遞到函數中,在函數中對參數所進行的修改,將影響到實際參數。
默認狀況下,Go 語言使用的是值傳遞,即在調用過程當中不會影響到實際參數。
A、函數做爲值
Go語言能夠很靈活的建立函數,並做爲值使用。
package main import ( "fmt" "math" ) func main(){ /* 聲明函數變量 */ getSquareRoot := func(x float64) float64 { return math.Sqrt(x) } /* 使用函數 */ fmt.Println(getSquareRoot(9)) }
B、閉包
Go語言支持匿名函數,可做爲閉包。匿名函數是一個"內聯"語句或表達式。匿名函數的優越性在於能夠直接使用函數內的變量,沒必要申明。
建立函數getSequence(),函數體內返回另一個函數。
func getSequence() func() int { i:=0 return func() int { i+=1 return i } }
C、方法
Go語言中同時有函數和方法。一個方法就是一個包含了接受者的函數,接受者能夠是命名類型或者結構體類型的一個值或者是一個指針。全部給定類型的方法屬於該類型的方法集。語法格式以下:
func (variable_name variable_data_type) function_name() [return_type]{ /* 函數體*/ }
方法實例以下:
/* 定義結構體 */ type Circle struct { radius float64 } //method 屬於 Circle 類型對象中的方法 func (c Circle) getArea() float64 { //c.radius 即爲 Circle 類型對象中的屬性 return 3.14 * c.radius * c.radius }
楊輝三角的實現以下:
//行數 const LINES int = 10 // 楊輝三角 func PascalTriangle() { nums := []int{} for i := 0; i < LINES; i++ { //補空白 for j := 0; j < (LINES - i); j++ { fmt.Print(" ") } for j := 0; j < (i + 1); j++ { var length = len(nums) var value int if j == 0 || j == i { value = 1 } else { value = nums[length-i] + nums[length-i-1] } nums = append(nums, value) fmt.Print(value, " ") } fmt.Println("") } }
變量是一種使用方便的佔位符,用於引用計算機內存地址。
Go語言的取地址符是&,放到一個變量前使用就會返回相應變量的內存地址。
指針變量指向了一個值的內存地址。
指針聲明格式以下:var var_name *var-type
var-type爲指針類型,var_name爲指針變量名,* 號用於指定變量是做爲一個指針。
var ip *int /* 指向整型*/ var fp *float32 /* 指向浮點型 */
指針使用流程:
A、定義指針變量。
B、爲指針變量賦值。
C、訪問指針變量中指向地址的值。
在指針類型前面加上*號(前綴)來獲取指針所指向的內容。
package main import "fmt" func main() { var a int= 20 /* 聲明實際變量 */ var ip *int /* 聲明指針變量 */ ip = &a /* 指針變量的存儲地址 */ fmt.Printf("a 變量的地址是: %x\n", &a ) /* 指針變量的存儲地址 */ fmt.Printf("ip 變量儲存的指針地址: %x\n", ip ) /* 使用指針訪問值 */ fmt.Printf("*ip 變量的值: %d\n", *ip ) }
當一個指針被定義後沒有分配到任何變量時,值爲nil。
nil指針也稱空指針。
nil在概念上和其它語言的null、None、nil、NULL同樣,都指代零值或空值。
一個指針變量一般縮寫爲ptr。
package main import "fmt" func main() { var ptr *int fmt.Printf("ptr 的值爲 : %x\n", ptr ) }
整型指針數組聲明以下:var ptr [MAX]*int;
ptr 爲整型指針數組。
package main import "fmt" const MAX int = 3 func main() { a := []int{10,100,200} var i int var ptr [MAX]*int; for i = 0; i < MAX; i++ { ptr[i] = &a[i] /* 整數地址賦值給指針數組 */ } for i = 0; i < MAX; i++ { fmt.Printf("a[%d] = %d\n", i,*ptr[i] ) } }
若是一個指針變量存放的又是另外一個指針變量的地址,則稱這個指針變量爲指向指針的指針變量。
當定義一個指向指針的指針變量時,第一個指針存放第二個指針的地址,第二個指針存放變量的地址:
指向指針的指針變量聲明格式以下:var ptr **int;
訪問指向指針的指針變量值須要使用兩個*號,以下所示:
package main import "fmt" func main() { var a int var ptr *int var pptr **int a = 3000 /* 指針 ptr 地址 */ ptr = &a /* 指向指針 ptr 地址 */ pptr = &ptr /* 獲取 pptr 的值 */ fmt.Printf("變量 a = %d\n", a ) fmt.Printf("指針變量 *ptr = %d\n", *ptr ) fmt.Printf("指向指針的指針變量 **pptr = %d\n", **pptr) }
Go語言容許向函數傳遞指針,只須要在函數定義的參數上設置爲指針類型便可。
package main import "fmt" func main() { /* 定義局部變量 */ var a int = 100 var b int= 200 fmt.Printf("交換前 a 的值 : %d\n", a ) fmt.Printf("交換前 b 的值 : %d\n", b ) /* 調用函數用於交換值 * &a 指向 a 變量的地址 * &b 指向 b 變量的地址 */ swap(&a, &b); fmt.Printf("交換後 a 的值 : %d\n", a ) fmt.Printf("交換後 b 的值 : %d\n", b ) } func swap(x *int, y *int) { var temp int temp = *x /* 保存 x 地址的值 */ *x = *y /* 將 y 賦值給 x */ *y = temp /* 將 temp 賦值給 y */ }