go語言學習

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

go語言菜鳥教程:http://www.runoob.com/go/go-tutorial.html

實效go編程:http://docscn.studygolang.com/doc/effective_go.html

線上go運行環境:https://tour.golang.org/welcome/1

go的安裝:參照這裡在Windows上安裝非常easy:http://www.runoob.com/go/go-environment.html

go中文標準庫(Ctrl+f):http://docscn.studygolang.com/pkg/#stdlib

go英文包索引與搜尋引擎:https://godoc.org/

/**********************************************************************************************************************/

gofmt 程式將Go程式按照標準風格縮排、 對齊,保留注釋並在需要時重新格式化。若你想知道如何處理一些新的代碼布局,請嘗試運行 gofmt

分號並不在源碼中出現。詞法分析器會自動插入分號。可以概括為: “如果新行前的標記為語句的末尾,則插入分號”。左大括弧不能放在下一行,如果這樣做,就會在大括弧前面插入一個分號,這可能引起不需要的效果。 

Go不再使用 do 或 while 迴圈,只有一個更通用的 forswitch 要更靈活一點;if 和 switch 像 for一樣可接受可選的初始化語句; 此外,還有一個包含類型選擇和多路通訊複用器的新控制結構:select。 其文法也有些許不同:沒有圓括弧,而其主體必須始終使用大括弧括住。

在變數與運算子間加入空格,程式看起來更加美觀。

Go 語言資料類型

布爾型
布爾型的值只可以是常量 true 或者 false。一個簡單的例子:var b bool = true。

數字類型
整型 int 和浮點型 float,Go 語言支援整型和浮點型數字,並且原生支援複數,其中位的運算採用補碼。

Go 也有基於架構的類型,例如:int、uint 和 uintptr。uint8uint16uint32uint64int8int16int32int64

浮點型:float32、float64。complex64(32 位實數和虛數)complex128(64 位元實數和虛數

字串類型:
字串就是一串固定長度的字元串連起來的字元序列。Go的字串是由單個位元組串連起來的。Go語言的字串的位元組使用UTF-8編碼標識Unicode文本。

Go 語言變數

Go 語言變數名由字母、數字、底線組成,其中首個字母不能為數字。

聲明變數的一般形式是使用 var 關鍵字。

第一種,指定變數類型,聲明後若不賦值,使用預設值,null 指標為nil

var name typename = value

第二種,根據值自行判定變數類型

var name = valuevar e, f = 123, "hello"

第三種,省略var, 注意 :=左側的變數不應該是已經聲明過的,否則會導致編譯錯誤。這種不帶聲明格式的只能在函數體中出現。由系統自動推斷,初始化聲明。

name := value//只能在函數體中出現// 例如var a int = 10var b = 10c : = 10

 第四種,多變數聲明(重要)

//類型相同多個變數, 非全域變數var vname1, vname2, vname3 typevname1, vname2, vname3 = v1, v2, v3var vname1, vname2, vname3 = v1, v2, v3 //和python很像,不需要顯示宣告類型,自動推斷vname1, vname2, vname3 := v1, v2, v3 //出現在:=左側的變數不應該是已經被聲明過的,否則會導致編譯錯誤// 這種因式分解關鍵字的寫法一般用於聲明全域變數var (    vname1 v_type1    vname2 v_type2)

實值型別和參考型別

所有像 int、float、bool 和 string 這些基本類型都屬於實值型別,使用這些類型的變數直接指向存在記憶體中的值。當使用等號 = 將一個變數的值賦值給另一個變數時,如:j = i,實際上是在記憶體中將 i 的值進行了拷貝。

如果你聲明了一個局部變數卻沒有在相同的代碼塊中使用它,同樣會得到編譯錯誤(a declared and not used) 但是全域變數是允許聲明但不使用。

多變數(已申明)可以在同一行進行賦值,如:

a, b, c = 5, 7, "abc"//未聲明,用:=a, b, c := 5, 7, "abc"

空白標識符 _ 也被用於拋棄值,如值 5 在:_, b = 5, 7 中被拋棄。_ 實際上是一個唯寫變數,你不能得到它的值。這樣做是因為 Go 語言中你必須使用所有被聲明的變數,但有時你並不需要使用從一個函數得到的所有傳回值。

Go 語言常量

const identifier [type] = value

常量還可以用作枚舉:

const (    Unknown = 0    Female = 1    Male = 2)

神奇的iota

/*iota,特殊常量,可以認為是一個可以被編譯器修改的常量。在每一個const關鍵字出現時,被重設為0,然後再下一個const出現之前,每出現一次iota,其所代表的數字會自動增加1。iota 可以被用作枚舉值:*/const (    a = iota    b = iota    c = iota)//簡寫形式const (    a = iota    b    c)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    )

一個更神奇的用法:

package mainimport "fmt"const (i=1<<iota  // i=1<<0     j=3<<iota  // j=3<<1    k          // k=3<<2 12    l          // j=3<<3 24)func main() {fmt.Println("i=",i)fmt.Println("j=",j)fmt.Println("k=",k)fmt.Println("l=",l)}//以上運行結果為:i= 1j= 6k= 12l= 24

邏輯運算子&&  ||  !就是判斷真假的

位元運算符&, |, 和 ^

位元運算符對整數在記憶體中的二進位位進行操作。對一個32位負數取非符號位的其他位a & 0x7fffffff

Go 語言 switch 語句

變數 var1 可以是任何類型,而 val1 和 val2 則可以是同類型的任意值。匹配項後面也不需要再加break,運行完後結束。

//Go 程式設計語言中 switch 語句的文法如下:switch var1 {    case val1:        ...    case val2:        ...    default:        ...}package mainimport "fmt"func main() {   /* 定義局部變數 */   var grade string = "B"   var marks int = 90   switch marks {      case 90: grade = "A"      case 80: grade = "B"      case 50,60,70 : grade = "C"      default: grade = "D"     }   switch {      case grade == "A" :         fmt.Printf("優秀!\n" )           case grade == "B", grade == "C" :         fmt.Printf("良好\n" )            case grade == "D" :         fmt.Printf("及格\n" )            case grade == "F":         fmt.Printf("不及格\n" )      default:         fmt.Printf("差\n" );   }   fmt.Printf("你的等級是 %s\n", grade );      }

Go 語言 select 語句

select是Go中的一個控制結構,類似於用於通訊的switch語句。每個case必須是一個通訊操作,要麼是發送要麼是接收。select隨機執行一個可啟動並執行case。如果沒有case可運行,它將阻塞,直到有case可運行。一個預設的子句應該總是可啟動並執行。

以下描述了 select 語句的文法:

*每個case都必須是一個通訊*所有channel運算式都會被求值*所有被發送的運算式都會被求值*如果任意某個通訊可以進行,它就執行;其他被忽略。*如果有多個case都可以運行,Select會隨機公平地選出一個執行。其他不會執行。 *否則:*如果有default子句,則執行該語句。*如果沒有default字句,select將阻塞,直到某個通訊可以運行;Go不會重新對channel或值進行求值。
package mainimport "fmt"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 語言 for 迴圈

搭配break,continue使用;Go語言的For迴圈有3中形式,只有其中的一種使用分號:

//和 C 語言的 for 一樣:for init; condition; post { }//和 C 的 while 一樣,取代while:for condition { }//和 C 的 for(;;) 一樣:for { }

for 迴圈的 range 格式可以對 slice、map、數組、字串等進行迭代迴圈。格式如下:

for key, value := range oldMap {    newMap[key] = value}

Go 語言函數

Go 語言函數定義格式如下:

func f(參數) (傳回值) {   函數體}//返回多個值func swap(x, y string) (string, string) {   return y, x}/* 函數返回兩個數的最大值 */func max(num1, num2 int) int {   var result int   if (num1 > num2) {      result = num1   } else {      result = num2   }   return result }

函數做為值使用:

package mainimport (   "fmt"   "math")func main(){   getSquareRoot := func(x float64) float64 {      return math.Sqrt(x)   }   fmt.Println(getSquareRoot(9))}

Go 語言匿名函數

func(參數列表) (傳回值列表) {       函數體... }
    //直接使用,無參數直接加括弧    func() int {        var i int =5        fmt.Printf("func 1\n")        return i    }()   //直接使用,有參數,在括弧裡加參數    func(arge int)  {          fmt.Printf("func %d\n",arge)    }(2)  //也可以先賦給一個變數再調用   a := func() int {          fmt.Printf("func 3\n")          return 5     }   a()

Go 語言數組

  • 數組是值。將一個數組賦予另一個數組會複製其所有元素。
  • 切片儲存了對底層數組的引用,若你將某個切片賦予另一個切片,它們會引用同一個數組。
  • 特別地,若將某個數組傳入某個函數,它將接收到該數組的一份副本而非指標。
  • 數組的大小是其類型的一部分。類型 [10]int 和 [20]int 是不同的。

Go 語言數組聲明需要指定元素類型及元素個數,文法格式如下:

var name [SIZE] type//var a [10] int//數組初始化:var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}//如果忽略[]中的數字不設定數組大小,Go 語言會根據元素的個數來設定數組的大小:var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}

Go 語言多維陣列

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type//var threedim [5][10][4]intvar a = [3][4]int{   {0, 1, 2, 3} ,   /*  第一行索引為 0 */ {4, 5, 6, 7} ,   /*  第二行索引為 1 */ {8, 9, 10, 11}   /*  第三行索引為 2 */}

Go 語言向函數傳遞數組

//指定大小void myFunction(param [10]int){...}//不指定大小void myFunction(param []int){...}//例子func getAverage(arr []int, size int) float32 {   var i,sum int   var avg float32     for i = 0; i < size;i++ {      sum += arr[i]   }   avg = float32(sum / size)   return avg;}

Go 語言指標

//指標聲明格式如下:var name *type//列印指標地址%x:fmt.Printf("變數的地址: %x\n", &a )//Go null 指標,它的值為 nilif(ptr == nil)

Go 語言指標數組

聲明整型指標數組(數組每個元素都是指標):var ptr [3]*int;

Go 語言指向指標的指標

var ptr **int;

Go 語言指標作為函數參數

func swap(x *int, y *int) {   var temp int   temp = *x    /* 儲存 x 地址的值 */   *x = *y      /* 將 y 賦值給 x */   *y = temp    /* 將 temp 賦值給 y */

Go 語言結構體

定義結構體和聲明變數

//結構體定義需要使用 type 和 struct 語句。//type 語句設定了結構體的名稱。結構體的格式如下:type my_type struct {   name1 type1   name2 type2   ...}一旦定義了結構體類型,它就能用於變數的聲明,文法格式如下:name := my_type {value1, value2...valuen}//例子:type Books struct {   title string   author string   subject string   book_id int}var Book1 BooksBook1.title = "Go 語言"Book1.author = "www.runoob.com"Book1.subject = "Go 語言教程"Book1.book_id = 6495407//結構體作為函數參數func printBook( book Books ) {}//結構體指標var ptr *Books

Go 語言切片(Slice)

Go 語言切片是對數組的抽象。Go 數組的長度不可改變。切片("動態數組"),長度是不固定的

切片儲存了對底層數組的引用,若你將某個切片賦予另一個切片,它們會引用同一個數組。

聲明一個未指定大小的數組來定義切片:var name []type或使用make()函數來建立切片:var slice1 []type = make([]type, len)或者make([]T, length, capacity)//capacity是選擇性參數也可以簡寫為:slice1 := make([]type, len)/************************************/s :=[] int {1,2,3 }            //直接初始化s := arr[:]                    //用數組初始化切片s := arr[startIndex:endIndex]  //新切片fmt.Printf("slice=%v\n",x)     //輸出切片2種方法 結果:slice=[0 0 0]fmt.Println("slice=", x)func printSlice(x []int){      //這個函數用於輸出切片資訊   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)}if(numbers == nil){            //判斷空切片      fmt.Printf("切片是空的")}

切片截取

package mainimport "fmt"func main() {   /* 建立切片 */   numbers := []int{0,1,2,3,4,5,6,7,8}      printSlice(numbers)   /* 列印原始切片 */   fmt.Println("numbers ==", numbers)   /* 列印子切片從索引1(包含) 到索引4(不包含)*/   fmt.Println("numbers[1:4] ==", numbers[1:4])   /* 預設下限為 0*/   fmt.Println("numbers[:3] ==", numbers[:3])   /* 預設上限為 len(s)*/   fmt.Println("numbers[4:] ==", numbers[4:])   numbers1 := make([]int,0,5)   printSlice(numbers1)   /* 列印子切片從索引  0(包含) 到索引 2(不包含) */   number2 := numbers[:2]   printSlice(number2)   /* 列印子切片從索引 2(包含) 到索引 5(不包含) */   number3 := numbers[2:5]   printSlice(number3)}func printSlice(x []int){   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)}

切片append()和 copy()

   var numbers []int   /* 允許追加空切片 */   numbers = append(numbers, 0)   /* 向切片添加一個元素 */   numbers = append(numbers, 1)   /* 同時添加多個元素 */   numbers = append(numbers, 2,3,4)   /* 建立切片 numbers1 是之前切片的兩倍容量*/   numbers1 := make([]int, len(numbers), (cap(numbers))*2)   /* 拷貝 numbers 的內容到 numbers1 */   copy(numbers1,numbers)

Go 語言範圍(Range)

//range一個切片,返回下標和對應項nums := []int{2, 3, 4}sum := 0for _, num := range nums {  sum += num}    //range也可以用在map的索引值對上。    kvs := map[string]string{"a": "apple", "b": "banana"}    for k, v := range kvs {        fmt.Printf("%s -> %s\n", k, v)    }    //range也可以用來枚舉Unicode字串。    //第一個參數是字元的索引,第二個是字元(Unicode的值)本身。    for i, c := range "go" {        fmt.Println(i, c)    }    //結果:    0 103    1 111    

Go 語言Map(集合)

Map 是一種無序的索引值對的集合。Map 是無序的,我們無法決定它的返回順序,這是因為 Map 是使用 hash 表來實現的。

/* 聲明變數,預設 map 是 nil ,nil map 不能用來存放索引值對*/var myname map[ktype]vtype/* 使用 make 函數,之後才能添加元素 */myname = make(map[ktype]vtype)
//例子   var countryCapitalMap map[string]string   /* 建立集合 */   countryCapitalMap = make(map[string]string)      /* map 插入 key-value 對,各個國家對應的首都 */   countryCapitalMap["France"] = "Paris"   countryCapitalMap["Italy"] = "Rome"   countryCapitalMap["Japan"] = "Tokyo"   countryCapitalMap["India"] = "New Delhi"      /* 使用 key 輸出 map 值 */   for country := range countryCapitalMap {      fmt.Println("Capital of",country,"is",countryCapitalMap[country])   }      /* 查看元素在集合中是否存在 */   captial, ok := countryCapitalMap["United States"]   /* 如果 ok 是 true, 則存在,否則不存在 */   if(ok){      fmt.Println("Capital of United States is", captial)     }else {      fmt.Println("Capital of United States is not present")    }

map中刪除元素

//delete(), 參數為 map 和其對應的 key/* 刪除元素 */delete(countryCapitalMap,"France");

Go 語言類型轉換

type(myname)   var a int = 17   var b int = 5   var c float32      c = float32(a)/float32(b)   fmt.Printf("c 的值為: %f\n",c)

Go 語言new

Go提供了兩種分配原語,即內建函數 new 和 make

new不會初始化記憶體,只會將記憶體置零。 也就是說,new(T) 會為類型為 T 的新項分配已置零的記憶體空間, 並返回它的地址,也就是一個類型為 *T 的值。

Go 語言make

內建函數 make(T, args) 的目的不同於 new(T)

它只用於建立切片、映射和通道,並傳回型別為 T(而非 *T)的一個已初始化 (而非置零)的值。 出現這種用差異的原因在於,這三種類型本質上為引用資料類型,它們在使用前必須初始化。

make 只適用於映射、切片和通道且不返回指標。若要獲得明確的指標, 請使用 new 分配記憶體(如下)。

var p *[]int = new([]int)       // 分配切片結構;*p == nil;基本沒用var v  []int = make([]int, 100) // 切片 v 現在引用了一個具有 100 個 int 元素的新數組// 沒必要的複雜:var p *[]int = new([]int)*p = make([]int, 100, 100)// 習慣用法:v := make([]int, 100)

Go 錯誤處理

Go 語言通過內建的錯誤介面提供了非常簡單的錯誤處理機制。

我們可以在編碼中通過實現 error 介面類型來建置錯誤資訊。

函數通常在最後的傳回值中返回錯誤資訊。

error類型是一個介面類型,這是它的定義:

type error interface {    Error() string}
package mainimport ("fmt")// 定義一個 DivideError 結構type DivideError struct {dividee intdivider int}// 實現`error`介面func (de *DivideError) Error() string {strFormat := `Cannot proceed, the divider is zero.dividee: %ddivider: 0`return fmt.Sprintf(strFormat, de.dividee)}// 定義 `int` 類型除法運算的函數func Divide(varDividee int, varDivider int) (result int, errorMsg string) {if varDivider == 0 {dData := DivideError{dividee: varDividee,divider: varDivider,}errorMsg = dData.Error()return} else {return varDividee / varDivider, ""}}func main() {// 正常情況if result, errorMsg := Divide(100, 10); errorMsg == "" {fmt.Println("100/10 = ", result)}// 當被除數為零的時候會返回錯誤資訊if _, errorMsg := Divide(100, 0); errorMsg != "" {fmt.Println("errorMsg is: ", errorMsg)}}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.