1. 程式人生 > >Go語言開發(二)、Go語言基礎

Go語言開發(二)、Go語言基礎

Go 語言 基礎

Go語言開發(二)、Go語言基礎

一、Go語言程序結構

Go語言程序基本結構如下:
A、包聲明
B、引入包
C、函數
D、變量
E、語句 & 表達式
F、註釋

package main //包聲明

import "fmt" //引入包

func main(){ //main函數
   //打印Hello World
   fmt.Print("Hello World!")
}

二、Go語言基礎語法

1、Go語言標記

Go語言程序由多個標記組成,可以是關鍵字、標識符、常量、字符串、符號。
fmt.Println("Hello, World!")語句由6個標記組成:

fmt
.
Println
(
"Hello, World!"
)

2、行分隔符

在Go語言程序中,一行代表一個語句結束。每個語句不需要像C家族中的其它語言一樣以分號;結尾。
如果打算將多個語句寫在同一行,則必須使用;人為區分,但在實際開發中不推薦。

fmt.Println("Hello, World!")
fmt.Println("Hello, Go!")

3、註釋

註釋不會被編譯,每一個包應該有相關註釋。
單行註釋是最常見的註釋形式,可以在任何地方使用以 // 開頭的單行註釋。 多行註釋也叫塊註釋,均已以 / 開頭,並以 / 結尾。

//打印hello world
   /*
   It print to console a string
   */

4、標識符

標識符用來命名變量、類型等程序實體。標識符是由一個或是多個字母(A~Z和a~z)數字(0~9)、下劃線_組成的序列,但第一個字符必須是字母或下劃線而不能是數字。無效的標識符如下:

1ab(以數字開頭)
case(Go語言的關鍵字)
a+b(運算符是不允許的)

5、關鍵字

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


程序一般由關鍵字、常量、變量、運算符、類型和函數組成。
程序中可能會使用到分隔符:括號 (),中括號 [] 和大括號 {}。
程序中可能會使用到標點符號:.、,、;、: 和 …。

6、空格

Go語言中變量的聲明必須使用空格隔開,如:
var age int;
語句中適當使用空格能讓程序看易閱讀。
無空格:
fruit=apples+oranges;
在變量與運算符間加入空格,程序看起來更加美觀,如:
fruit = apples + oranges;

7、可見性規則

Go語言中,使用大小寫來決定常量、變量、類型、接口、結構或函數是否可以被外部包所調用。
函數名首字母小寫即為private :
func getId() {}
函數名首字母大寫即為public :
func Printf() {}

8、Package

Go語言程序通過package來組織,只有package名稱為main的包可以包含main函數。
一個可執行程序有且僅有一個main包。
通過import關鍵字來導入其他非main包。
可以通過import關鍵字單個導入:

    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語言數據類型

在Go編程語言中,數據類型用於聲明函數和變量。
數據類型是為了把數據分成所需內存大小不同的數據,編程的時候需要用大數據的時候才需要申請大內存,就可以充分利用內存。

1、bool

布爾型的值只可以是常量true或者false。
var b bool = true

2、數字類型

整型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:無符號整型,用於存放一個指針

3、字符串類型

字符串就是一串固定長度的字符連接起來的字符序列。Go語言的字符串是由單個字節連接起來的。Go語言的字符串的字節使用UTF-8編碼標識Unicode文本。

4、派生類型

派生類型包括:
A、指針類型(Pointer)
B、數組類型
C、結構化類型(struct)
D、Channel 類型
E、函數類型
F、切片類型
G、接口類型(interface)
H、Map 類型

四、Go語言變量

1、Go語言變量簡介

變量是計算機語言中能儲存計算結果或能表示值的抽象概念。變量可以通過變量名訪問。
Go 語言變量名由字母、數字、下劃線組成,其中首個字母不能為數字。

2、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

3、Go語言多變量聲明

//類型相同多個變量, 非全局變量
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"

4、值類型和引用類型

int、float、bool、string等基本類型都屬於值類型,值類型的變量直接指向存在內存中的值。
當使用等號=將一個變量的值賦值給另一個變量時,如:j = i,實際上是在內存中將i的值進行拷貝。
可以通過&i來獲取變量i的內存地址,例如0xf840000040(地址隨機)。值類型的變量的值存儲在棧中。
內存地址會根據機器的不同而有所不同,相同的程序在不同的機器上執行後也會有不同的內存地址。因為每臺機器可能有不同的存儲器布局,並且位置分配也可能不同。
更復雜的數據通常會需要使用多個字,一般使用引用類型保存。
一個引用類型的變量r1存儲的是r1的值所在的內存地址(數字),或內存地址中第一個字所在的位置。
同一個引用類型的指針指向的多個字可以是在連續的內存地址中(內存布局是連續的),也可以將這些字分散存放在內存中,每個字都指示了下一個字所在的內存地址。
當使用賦值語句r2 = r1時,只有引用(地址)被復制。
如果r1的值被改變,r1的所有引用都會指向被修改後的內容。
技術分享圖片

五、Go語言變量作用域

1、Go語言變量作用域簡介

作用域為已聲明標識符所表示的常量、類型、變量、函數或包在源代碼中的作用範圍。
Go語言中變量可以在三個地方聲明:
A、函數內定義的變量稱為局部變量
B、函數外定義的變量稱為全局變量
C、函數定義中的變量稱為形式參數

2、局部變量

在函數體內聲明的變量為局部變量,其作用域只在函數體內,參數和返回值變量也是局部變量。

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)
}

3、全局變量

在函數體外聲明的變量為全局變量,全局變量可以在整個包甚至外部包(被導出後)使用。

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)
}

4、形式參數

形式參數會作為函數的局部變量來使用。

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;
}

5、局部和全局變量的初始化

不同類型的局部和全局變量默認值為:
int 0
float32 0
pointer nil

六、Go語言常量

1、Go語言常量

常量是一個簡單值的標識符,在程序運行時,不會被修改的量。
常量中的數據類型只可以是布爾型、數字型(整數型、浮點型和復數)和字符串型。

2、Go語言常量聲明

常量的定義格式:
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)
}

3、Go語言枚舉

常量可以用作枚舉:

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)
}

4、iota

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語言運算符

1、Go語言運算符簡介

運算符用於在程序運行時執行數學或邏輯運算。Go語言內置的運算符有:
A、算術運算符
B、關系運算符
C、邏輯運算符
D、位運算符
E、賦值運算符
F、其它運算符

2、算術運算符

+    相加     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)
}

3、關系運算符

==:檢查兩個值是否相等,如果相等返回 True 否則返回 False。
!=:檢查兩個值是否不相等,如果不相等返回 True 否則返回 False。
>:檢查左邊值是否大於右邊值,如果是返回 True 否則返回 False。
<:檢查左邊值是否小於右邊值,如果是返回 True 否則返回 False。
>=:檢查左邊值是否大於等於右邊值,如果是返回 True 否則返回 False。
<=:檢查左邊值是否小於等於右邊值,如果是返回 True 否則返回 False。

4、邏輯運算符

&&:邏輯AND運算符。 如果兩邊的操作數都是True,則條件True,否則為False。 
||:邏輯OR運算符。 如果兩邊的操作數有一個True,則條件True,否則為False。
!:邏輯NOT運算符。 如果條件為True,則邏輯NOT條件False,否則為True。

5、位運算符

&:按位與運算符"&"是雙目運算符,功能是參與運算的兩數各對應的二進位進行相與。 
|:按位或運算符"|"是雙目運算符,功能是參與運算的兩數各對應的二進位進行相或。
^:按位異或運算符"^"是雙目運算符,功能是參與運算的兩數各對應的二進位進行相異或,當兩對應的二進位相異時,結果為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 )
}

6、賦值運算符

=:簡單的賦值運算符,將一個表達式的值賦給一個左值
+=:相加後再賦值
-=:相減後再賦值
*=:相乘後再賦值
/=:相除後再賦值
%=:求余後再賦值
<<=:左移後賦值
>>=:右移後賦值
&=:右移後賦值
^=:按位異或後賦值
|=:按位或後賦值

賦值運算符實例:

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 )

}

7、其它運算符

&:返回變量存儲地址
*:指針變量

實例:

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);
}

8、運算符優先級

有些運算符擁有較高的優先級,二元運算符的運算方向均是從左至右。
優先級 運算符

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)
}

八、Go語言條件語句

1、條件語句簡介

條件語句需要開發者通過指定一個或多個條件,並通過測試條件是否為 true來決定是否執行指定語句,並在條件為false的情況在執行另外的語句。
條件語句的結構如下:
技術分享圖片

2、if語句

if語句由一個布爾表達式後緊跟一個或多個語句組成。
Go編程語言中if語句的語法如下:

if 布爾表達式 {
   /* 在布爾表達式為 true 時執行 */}

If在布爾表達式為true時,其後緊跟的語句塊執行,如果為false則不執行。
技術分享圖片

3、if...else語句

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")
   }
}

4、if嵌套語句

if或else if語句中嵌入一個或多個if或else if語句。

5、switch語句

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("未知型")
}

6、select語句

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")
   }
}

九、Go語言循環語句

1、循環語句簡介

實際問題中有許多具有規律性的重復操作,因此在程序中就需要重復執行某些語句。
循環語句的結構如下:
技術分享圖片

2、for循環

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)
   }
}

3、循環嵌套

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);
      }
   }
}

4、循環控制語句

循環控制語句可以控制循環體內語句的執行過程。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++
}

5、無限循環

如果循環中條件語句永遠不為false,則會進行無限循環。可以通過for循環語句中只設置一個條件表達式來實現無限循環。

for true{
   fmt.Printf("這是無限循環。\n");
}

十、Go語言函數

1、Go語言函數簡介

函數是基本的代碼塊,用於執行一個任務。
Go語言最少有個main()函數。
可以通過函數來劃分不同功能,邏輯上每個函數執行的是指定的任務。
函數聲明告訴編譯器函數的名稱、返回類型和參數。
Go語言標準庫提供了多種可用的內置的函數。例如,len()函數可以接受不同類型參數並返回該類型的長度。如果傳入的是字符串則返回字符串的長度,如果傳入的是數組,則返回數組中包含的元素個數。

2、函數定義

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
}

3、函數調用

當創建函數時,定義函數需要做什麽,通過調用該函數來執行指定任務。
調用函數,向函數傳遞參數,並返回值,例如:

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
}

4、函數返回值

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)
}

5、函數參數

函數如果使用參數,參數變量稱為函數的形參。
調用函數,可以通過兩種方式來傳遞參數:
A、值傳遞
值傳遞是指在調用函數時將實際參數復制一份傳遞到函數中,在函數中如果對參數進行修改,將不會影響到實際參數。
B、引用傳遞
引用傳遞是指在調用函數時將實際參數的地址傳遞到函數中,在函數中對參數所進行的修改,將影響到實際參數。
默認情況下,Go 語言使用的是值傳遞,即在調用過程中不會影響到實際參數。

6、函數用法

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語言指針

1、Go語言指針的定義

變量是一種使用方便的占位符,用於引用計算機內存地址。
Go語言的取地址符是&,放到一個變量前使用就會返回相應變量的內存地址。
指針變量指向了一個值的內存地址。
指針聲明格式如下:
var var_name *var-type
var-type為指針類型,var_name為指針變量名,* 號用於指定變量是作為一個指針。

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮點型 */

2、Go語言指針的使用

指針使用流程:
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 )
}

3、Go語言空指針

當一個指針被定義後沒有分配到任何變量時,值為nil。
nil指針也稱空指針。
nil在概念上和其它語言的null、None、nil、NULL一樣,都指代零值或空值。
一個指針變量通常縮寫為ptr。

package main

import "fmt"

func main() {
   var  ptr *int

   fmt.Printf("ptr 的值為 : %x\n", ptr  )
}

4、Go語言指針數組

整型指針數組聲明如下:
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] )
   }
}

5、Go語言二級指針

如果一個指針變量存放的又是另一個指針變量的地址,則稱這個指針變量為指向指針的指針變量。
當定義一個指向指針的指針變量時,第一個指針存放第二個指針的地址,第二個指針存放變量的地址:
技術分享圖片
指向指針的指針變量聲明格式如下:
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)
}

6、Go語言指針參數

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 */
}

Go語言開發(二)、Go語言基礎