Golang 語法結(jié)構(gòu)與類型

參考:the-way-to-go_ZH_CN苞冯、books.studygolang.com

一、文件名、關(guān)鍵字與標(biāo)識符

  • 文件名以.go結(jié)尾

  • 標(biāo)識符與 C 家族中的其它語言相同。

    36 個(gè)預(yù)定義標(biāo)識符

    append bool byte cap close complex complex64 complex128 uint16
    copy false float32 float64 imag int int8 int16 uint32
    int32 int64 iota len make new nil panic uint64
    print println real recover string true uint uint8 uintptr
  • 25個(gè)關(guān)鍵字

    break default func interface select
    case defer go map struct
    chan else goto package switch
    const fallthrough if range type
    continue for import return var
  • golang程序規(guī)范

    • 命名使用駝峰命名法,且不能出現(xiàn)下劃線
    • 根據(jù)首字母的大小寫來確定訪問權(quán)限追迟。無論是方法脆荷、常量、變量或結(jié)構(gòu)體的名稱集晚。
      • 如果使用首字母大寫窗悯,則可以被其他包訪問
      • 如果首字母小寫,則只能在本包中使用偷拔。
    • 結(jié)構(gòu)體中屬性名的大寫蒋院,如果屬性名小寫,則會(huì)在數(shù)據(jù)解析時(shí)(如json解析或?qū)⒔Y(jié)構(gòu)體作為請求或訪問參數(shù))時(shí)無法解析莲绰。

二欺旧、基本結(jié)構(gòu)和要素

package main    //歸屬于main包

import "fmt"    // 導(dǎo)入 fmt 包(函數(shù)或其他元素)

//實(shí)現(xiàn)main包中的main函數(shù),該函數(shù)會(huì)自動(dòng)執(zhí)行
func main() {
    fmt.Println("hello, world")  // fmt 包中的 Println 函數(shù)蛤签,可以將字符串輸出到控制臺辞友,并在最后自動(dòng)增加換行字符 \n
}

1.包的概念、導(dǎo)入與可見性

1)文件的歸屬與包的導(dǎo)入

  • 源文件中非注釋的第一行指明這個(gè)文件屬于哪個(gè)包顷啼,如:package main踏枣。

    • package main表示一個(gè)可獨(dú)立執(zhí)行的程序,不指定屬于main包的源程序钙蒙,則會(huì)被編譯為包(所有的包名都應(yīng)該使用小寫字母)茵瀑。
    • 可以用一些較小的文件,并且在每個(gè)文件非注釋的第一行都使用 package main 來指明這些文件都屬于 main 包躬厌。
  • Go 程序是通過 import 關(guān)鍵字導(dǎo)入一組包马昨,包名被封閉在半角雙引號 "" 中。

    //import "包的路徑或 URL 地址" 
    import "fmt"
    import "os"
    
    // 或
    import (
       "fmt"
       "os"
    ) // 被稱為因式分解關(guān)鍵字
    
    //導(dǎo)入外部安裝包
      //先安裝外部包到 $GOROOT/src/ 目錄
    go install codesite.ext/author/goExample/goex
    import goex "codesite.ext/author/goExample/goex"
    
    • 包在導(dǎo)入是可以使用相對路徑或絕對路徑
    • 如果想要構(gòu)建一個(gè)程序扛施,則包和包內(nèi)的文件都必須以正確的順序進(jìn)行編譯鸿捧。包的依賴關(guān)系決定了其構(gòu)建順序。
  • Go 的標(biāo)準(zhǔn)庫包含了大量的包(如:fmt 和 os)疙渣,存放在 $GOROOT/pkg/$GOOS_$GOARCH/ 目錄下匙奴。

    • os: 提供一個(gè)平臺無關(guān)性的操作系統(tǒng)功能接口,采用類Unix設(shè)計(jì)妄荔,隱藏了不同操作系統(tǒng)間差異泼菌,讓不同的文件系統(tǒng)和操作系統(tǒng)對象表現(xiàn)一致。
    • os/exec: 提供運(yùn)行外部操作系統(tǒng)命令和程序的方式啦租。
    • syscall: 底層的外部包哗伯,提供了操作系統(tǒng)底層調(diào)用的基本接口。
  • 同一個(gè)包的源文件必須全部被一起編譯篷角。

    • 對一個(gè)包進(jìn)行更改或重新編譯焊刹,所有引用了這個(gè)包的程序都必須全部重新編譯。

2)可見性規(guī)則

  • 當(dāng)標(biāo)識符(包括常量、變量虐块、類型俩滥、函數(shù)名、結(jié)構(gòu)字段等等)以一個(gè)大寫字母開頭非凌,如:Group1举农,那么使用這種形式的標(biāo)識符的對象就可以被外部包的代碼所使用(客戶端程序需要先導(dǎo)入這個(gè)包),這被稱為導(dǎo)出(像面向?qū)ο笳Z言中的 public)敞嗡;
  • 標(biāo)識符如果以小寫字母開頭,則對包外是不可見的航背,但是他們在整個(gè)包的內(nèi)部是可見并且可用的(像面向?qū)ο笳Z言中的 private )喉悴。

3)包的分級聲明和初始化

  • 包內(nèi)可以定義或聲明 0 個(gè)或多個(gè)常量(const)、變量(var)和類型(type)玖媚,這些對象的作用域都是全局的(在本包范圍內(nèi))箕肃。

2.注釋

  • 單行注釋以 // 開頭。
  • 多行注釋均以 /* 開頭今魔,并以 */ 結(jié)尾勺像。
  • 每一個(gè)包應(yīng)該有相關(guān)注釋,在 package 語句之前的塊注釋將被默認(rèn)認(rèn)為是這個(gè)包的文檔說明
  • 所有全局作用域的類型错森、常量吟宦、變量、函數(shù)和被導(dǎo)出的對象都應(yīng)該有一個(gè)合理的注釋涩维。
  • godoc 工具會(huì)收集這些注釋并產(chǎn)生一個(gè)技術(shù)文檔殃姓。

3.打印

Go中的fmt幾種輸出的區(qū)別和格式化方式

fmt包有printf與println兩個(gè)打印函數(shù)

  • Println :可以打印字符串和變量

    a := 10
    fmt.Println(a) 
    fmt.Println("abc")
    
  • Printf : 可以打印出格式化的字符串,可以輸出字符串類型的變量瓦阐,不可以輸出其他類型變量

    fmt.Printf("%v", str)
    
    //通用的占位符
    %v     值的默認(rèn)格式蜗侈。
    %+v   類似%v,但輸出結(jié)構(gòu)體時(shí)會(huì)添加字段名
    %#v  相應(yīng)值的Go語法表示 
    %T    相應(yīng)值的類型的Go語法表示 
    %%    百分號,字面上的%,非占位符含義
    
    //默認(rèn)格式%v下睡蟋,對于不同的數(shù)據(jù)類型踏幻,底層會(huì)去調(diào)用默認(rèn)的格式化方式:
    bool:                    %t 
    int, int8 etc.:          %d 
    uint, uint8 etc.:        %d, %x if printed with %#v
    float32, complex64, etc: %g
    string:                  %s
    chan:                    %p 
    pointer:                 %p
    

4.變量、常量和類型

Go語言變量和常量的聲明方式與C和C++語言明顯不同戳杀, Go語言引入了關(guān)鍵字var该面,而類型信息放在變量或常量名之后。

1)變量

  • 變量的聲明

    var v1 int
    var v2 string
    var v3 [10]int // 數(shù)組
    var v4 []int // 數(shù)組切片
    var v5 struct {
    f int
    }
    var v6 *int // 指針
    var v7 map[string]int // map豺瘤, key為string類型吆倦, value為int類型
    var v8 func(a int) int
    
    • Go 語言不使用分號作為語句的結(jié)束,實(shí)際上這一過程是由編譯器自動(dòng)完成坐求。
  • 變量的聲明及初始化

    //  var關(guān)鍵字可以保留蚕泽,但不再是必要的元素
    var v1 int = 10 // 正確的使用方式1
    var v2 = 10 // 正確的使用方式2,編譯器可以自動(dòng)推導(dǎo)出v2的類型
    v3 := 10 // 正確的使用方式3,編譯器可以自動(dòng)推導(dǎo)出v3的類型
      // :=左側(cè)的變量不應(yīng)該是已經(jīng)被聲明過的须妻,否則會(huì)導(dǎo)致編譯錯(cuò)誤
    
  • 變量的賦值

    var v10 int
    v10 = 123
    
  • 變量匿名

    在調(diào)用函數(shù)時(shí)為了獲取一個(gè)值仔蝌,卻因?yàn)樵摵瘮?shù)返回多個(gè)值而不得不定義一堆沒用的變量。Go可以通過結(jié)合使用多重返回和匿名變量來避免這種丑陋的寫法

    func GetName() (firstName, lastName, nickName string) {
      return "May", "Chan", "Chibi Maruko"
    }
    _, _, nickName := GetName()
    

2)常量

  • 常量的聲明及初始化

    const Pi float64 = 3.14159265358979323846
    const zero = 0.0 // 無類型浮點(diǎn)常量
    const (
        size int64 = 1024
        eof = -1 // 無類型整型常量
    )
    const u, v float32 = 0, 3 // u = 0.0, v = 3.0荒吏,常量的多重賦值
    const a, b, c = 3, 4, "foo"
    // a = 3, b = 4, c = "foo", 無類型整型和字符串常量
    
  • 預(yù)定義常量: true敛惊、 false和iota。

    //iota被認(rèn)為是一個(gè)可被編譯器修改的常量绰更,在每一個(gè)const關(guān)鍵字出現(xiàn)時(shí)被重置為0瞧挤,然后在下一個(gè)const出現(xiàn)之前,每出現(xiàn)一次iota儡湾,其所代表的數(shù)字會(huì)自動(dòng)增1特恬。
    const ( // iota被重設(shè)為0
        c0 = iota // c0 == 0
        c1 = iota // c1 == 1
        c2 = iota // c2 == 2
    )
    
    const (
        u = iota * 42 // u == 0
        v float64 = iota * 42 // v == 42.0
        w = iota * 42 // w == 84
    )
    
    //如果兩個(gè)const的賦值語句的表達(dá)式是一樣的,那么可以省略后一個(gè)賦值表達(dá)式徐钠。
    const ( // iota被重設(shè)為0
        c0 = iota // c0 == 0
        c1 // c1 == 1
        c2 // c2 == 2
    )
    

3)類型

  • 基礎(chǔ)類型

    • 布爾類型: bool
    • 整型: int8癌刽、 byte、 int16尝丐、 int显拜、 uint、 uintptr等
    • 浮點(diǎn)類型: float32爹袁、 float64远荠。
    • 復(fù)數(shù)類型: complex64、 complex128呢簸。
    • 字符串: string矮台。
    • 字符類型: rune。
    • 錯(cuò)誤類型: error根时。
  • 復(fù)合類型

    • 指針(pointer)

    • 數(shù)組(array)

      //數(shù)組(array)
      var a [3]int
      

    var b [3]int = [3]int{1, 2, 3}
    c := [...]int{1, 2}
    fmt.Println(a[0])
    //二維數(shù)組
    d := [3][5]int
    d[0][1] = 0

    
    - 切片(slice)
    
    - Slice(切片)代表變長的序列瘦赫,序列中每個(gè)元素都有相同的類型。一個(gè)slice類型一般寫作[]T蛤迎,其中T代表slice中元素的類型确虱;slice的語法和數(shù)組很像,只是沒有固定長度而已替裆。
    
      ```go
      //聲明切片的格式
      var identifier []type   //不需要說明長度
      d := [...]int{1, 2,3,4,5,6,7,8,9}
      var slice1 []int = d[2:5]
    
      //用 make() 創(chuàng)建一個(gè)切片
    slice1 := make([]int, 50, 100)
      //用 new() 創(chuàng)建一個(gè)切片
      slice2 := new([100]int)[0:50]
      ```
    
    - 字典(map)
    
    - map類型可以寫為map[K]V校辩,其中K和V分別對應(yīng)key和value。
    
      ```go
      ages := map[string]int{
          "alice":   31,
          "charlie": 34,
      }
      ages["alice"] = 32
      fmt.Println(ages["alice"]) // "32"
      ```
    
    - 通道(chan)
    
    - 結(jié)構(gòu)體(struct)
    
    ```go
    type Employee struct {
        ID        int                   //編譯器在行末自動(dòng)添加逗號
        Name      string    
        Address   string
        DoB       time.Time
        Position  string
        Salary    int
        ManagerID int
    }
    var dilbert Employee
    
    • 接口(interface)

      • interface說明

      • interface是一組方法簽名的組合

      • 空interface(interface{})不包含任何的方法辆童,空接口類型對滿足它的類型沒有要求宜咒,所以我們可以為空接口分配任何值。

        var any interface{}
        any = true
        any = 12.34
        any = "hello"
        any = map[string]int{"one": 1}
        any = new(bytes.Buffer)
        
        // interface轉(zhuǎn)換成具體類型調(diào)用方式:interfaceVar.(具體類型)
        // 原理:斷言
        any.(int)
        any.(string)
        any.(byte)
        any.(float32)
        
    • JSON

      • JavaScript對象表示法(JSON)是一種用于發(fā)送和接收結(jié)構(gòu)化信息的標(biāo)準(zhǔn)協(xié)議把鉴。JSON是對JavaScript中各種類型的值(字符串故黑、數(shù)字儿咱、布爾值)和對象(Unicode本文)的編碼。

        //1.編組(marshaling):結(jié)構(gòu)體slice轉(zhuǎn)為JSON格式數(shù)據(jù)
        type Movie struct {
            Title  string
            Year   int  `json:"released"`
            Color  bool `json:"color,omitempty"`
            Actors []string
        }
        
        var movies = []Movie{
            {Title: "Casablanca", Year: 1942, Color: false,
                Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}},
            {Title: "Cool Hand Luke", Year: 1967, Color: true,
                Actors: []string{"Paul Newman"}},
            {Title: "Bullitt", Year: 1968, Color: true,
                Actors: []string{"Steve McQueen", "Jacqueline Bisset"}},
            // ...
        }
        
        data, err := json.Marshal(movies)
        if err != nil {
            log.Fatalf("JSON marshaling failed: %s", err)
        }
        fmt.Printf("%s\n", data)
        //打印結(jié)果
        [{"Title":"Casablanca","released":1942,"Actors":["Humphrey Bogart","Ingr
        id Bergman"]},{"Title":"Cool Hand Luke","released":1967,"color":true,"Ac
        tors":["Paul Newman"]},{"Title":"Bullitt","released":1968,"color":true,"
        Actors":["Steve McQueen","Jacqueline Bisset"]}]
                                                         
        //2.將JSON格式數(shù)據(jù)解碼為一個(gè)結(jié)構(gòu)體slice
        var titles []struct{ Title string }
                                                         
        if err := json.Unmarshal(data, &titles); err != nil {
          log.Fatalf("JSON unmarshaling failed: %s", err)
        }
        fmt.Println(titles) // "[{Casablanca} {Cool Hand Luke} {Bullitt}]"                
        

4)自定義類型

使用關(guān)鍵字type自定義類型

//自定義類型
type IZ int
var a IZ = 5

//定義多類型场晶,使用因式分解關(guān)鍵字的方式
type (
   IZ int
   FZ float64
   STR string
)

5)類型轉(zhuǎn)換

//int與float轉(zhuǎn)換
var a float32 = 1234.12345678
b := int64(a)
c := float32(a)
d := float64(a)
e := float64(c)

// []byte轉(zhuǎn)int(16進(jìn)制轉(zhuǎn)10進(jìn)制)
import "fmt"
import "encoding/binary"
var a []byte = []byte{0, 1, 2, 3}  
binary.BigEndian.Uint32(a)      //0x00010203 ==> 66051
binary.LittleEndian.Uint32(a) //0x03020100 ==> 50462976

b  : = []byte{0x00, 0x00, 0x03, 0xe8}  
b_buf  : =  bytes .NewBuffer(b)  
var x int32  
binary.Read(b_buf, binary.BigEndian, &x)  
fmt.Println(x)  

b := []byte{0xe8, 0x03, 0xd0, 0x07}
x1 := binary.LittleEndian.Uint32(b[0:])

// int 轉(zhuǎn) []byte
x  =  1000  
b_buf  :=  bytes .NewBuffer([]byte{})  
binary.Write(b_buf, binary.BigEndian, x)  
fmt.Println(b_buf.Bytes())  

// float32 轉(zhuǎn)uint32
math.Float32bits(f float32) uint32

// uint32 轉(zhuǎn) float32
Float32frombits(b uint32) float32

//uint32 轉(zhuǎn) []byte
func EncodeUint32(v uint32) []uint8 {
    b := make([]uint8, 4)
    binary.LittleEndian.PutUint32(b, v)
    return b
}

// string 轉(zhuǎn) []byte
var str string = "test"
var data []byte = []byte(str)

// []byte 轉(zhuǎn) string
var data [10]byte 
var str string = string(data[:])

// []byte -> String  (byte轉(zhuǎn)ascii)
data1 := []byte{0x31, 0x32, 0x33, 0x34}
data2 := []byte("Hello")
str1 := string(data1)  //"1234"
str2 := string(data2)  //"Hello"
// []byte -> String  (byte轉(zhuǎn)hex)
import "encoding/hex"
hexstr := hex.EncodeToString(data1)     //"31323334"
// String -> []byte (hex轉(zhuǎn)byte)
tmp, _ := hex.DecodeString(hexstr)  //[49 50 51 52]


//===strconv包實(shí)現(xiàn)基本數(shù)據(jù)類型的字符串表示形式之間的轉(zhuǎn)換===
import "strconv"
//數(shù)值轉(zhuǎn)換
    //int轉(zhuǎn)string
    strconv.Itoa(i int) string
    //string轉(zhuǎn)int
    strconv.Atoi(s string) (i int, err error)
//將字符串轉(zhuǎn)換為值
    //string轉(zhuǎn)bool
    b, err := strconv.ParseBool("true")
    //string轉(zhuǎn)float64
    f, err := strconv.ParseFloat("3.1415", 64)
    //string轉(zhuǎn)int64混埠,10進(jìn)制表示
    i, err := strconv.ParseInt("-42", 10, 64)
    //string轉(zhuǎn)uint64
    u, err := strconv.ParseUint("42", 10, 64)
//將值轉(zhuǎn)換為字符串
    //bool轉(zhuǎn)string
    s := strconv.FormatBool(true)
    //float64轉(zhuǎn)string 64
    s := strconv.FormatFloat(3.1415, 'E', -1, 64)
    //int64轉(zhuǎn)string,以10進(jìn)制顯示
    s := strconv.FormatInt(-42, 10)
    //uint64轉(zhuǎn)string诗轻,以10進(jìn)制顯示
    s := strconv.FormatUint(42, 10)

5.運(yùn)算符

  • 數(shù)值運(yùn)算

  • 比較運(yùn)算

    ==钳宪、!=<扳炬、<=吏颖、>>=

  • 位運(yùn)算

    按位與 &鞠柄、按位或 |侦高、按位異或 ^

  • 字符串操作

    //字符串拼接
    s := "hel" + "lo,"
    s += "world!"
    strings.Join(sl []string, sep string) string
    //字符串分割
    //將會(huì)利用 1 個(gè)或多個(gè)空白符號來作為動(dòng)態(tài)長度的分隔符將字符串分割成若干小塊
    sl := strings.Fields(str)
    for _, val := range sl {
        fmt.Printf("%s - ", val)
    }
    //自定義分割符號來對指定字符串進(jìn)行分割
    sl2 := strings.Split(str2, "|")
    for _, val := range sl2 {
        fmt.Printf("%s - ", val)
    }
    // 注意:val[1:len(val)-1]才是真正的目標(biāo)字符串
    
    //判斷前綴
    strings.HasPrefix(str, "Th") bool
    //判斷后綴
    strings.HasSuffix(str, "er")  bool
    
    //字符串包含關(guān)系
    strings.Contains(str, substr)  bool
    
    //判斷子字符串或字符在父字符串中首次出現(xiàn)的位置
    strings.Index(s, str string)  int
    //判斷子字符串或字符在父字符串中最后出現(xiàn)的位置
    strings.LastIndex(s, str string) int
    
    //字符串替換
    //將字符串 str 中的前 n 個(gè)字符串 old 替換為字符串 new,  n = -1 則替換所有字符
    strings.Replace(str, old, new, n) string
    
    //統(tǒng)計(jì)字符串出現(xiàn)次數(shù)
    strings.Count(s, str) int
    
    //修改字符串大小寫
    strings.ToLower(s) string
    strings.ToUpper(s) string
    

6.Go 程序的一般結(jié)構(gòu)示例

package main  //被 main 包引用厌杜,是一個(gè)可獨(dú)立執(zhí)行的程序

import (
   "fmt"
)

const c = "C"

var v int = 5

type T struct{}

//每個(gè)源文件都只能包含一個(gè) init 函數(shù), 執(zhí)行優(yōu)先級比 main 函數(shù)高
func init() { // initialization of package
}

func main() {
   var a int
   Func1()
   // ...
   fmt.Println(a)
}

func (t T) Method1() {
   //...
}

func Func1() { // exported function Func1
   //...
}

Go 程序的執(zhí)行順序:

  1. 按順序?qū)胨斜?main 包引用的其它包登馒,然后在每個(gè)包中執(zhí)行如下流程:
  2. 如果該包又導(dǎo)入了其它的包,則從第一步開始遞歸執(zhí)行,但是每個(gè)包只會(huì)被導(dǎo)入一次。
  3. 然后以相反的順序在每個(gè)包中初始化常量和變量,如果該包含有 init 函數(shù)的話寨躁,則調(diào)用該函數(shù)话肖。
  4. 在完成這一切之后,main 也執(zhí)行同樣的過程,最后調(diào)用 main 函數(shù)開始執(zhí)行程序。

三蒂培、控制結(jié)構(gòu)

1.if-else

if condition1 {
    // do something 
} else if condition2 {
    // do something else    
} else {
    // catch-all or default
}

//示例
func main() {
    var first int = 10
    var cond int

    if first <= 0 {
        fmt.Printf("first is less than or equal to 0\n")
    } else if first > 0 && first < 5 {
        fmt.Printf("first is between 0 and 5\n")
    } else {
        fmt.Printf("first is 5 or greater\n")
    }
    if cond = 5; cond > 10 {
        fmt.Printf("cond is greater than 10\n")
    } else {
        fmt.Printf("cond is not greater than 10\n")
    }
}

2.switch

// 方式1
switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}

//示例
func main() {
    var num1 int = 100

    switch num1 {
    case 98, 99:
        fmt.Println("It's equal to 98")
    case 100: 
        fmt.Println("It's equal to 100")
    default:
        fmt.Println("It's not equal to 98 or 100")
    }
}

//方式2
switch {
    case condition1:
        ...
    case condition2:
        ...
    default:
        ...
}

//示例
func main() {
    var num1 int = 7

    switch {
        case num1 < 0:
            fmt.Println("Number is negative")
        case num1 > 0 && num1 < 10:
            fmt.Println("Number is between 0 and 10")
        default:
            fmt.Println("Number is 10 or greater")
    }
}

3.for

// 格式
for 初始化語句; 條件語句; 修飾語句 {
        // do something 
}

//示例
func main() {
    for i := 0; i < 5; i++ {
        fmt.Printf("This is the %d iteration\n", i)
    }
}

//for-range 結(jié)構(gòu)
for i, char := range str {
    ...
}
//示例
func main() {
    str := "Go is a beautiful language!"
    fmt.Printf("The length of str is: %d\n", len(str))
    for pos, char := range str {
        fmt.Printf("Character on position %d is: %c \n", pos, char)
    }
}

四钳枕、函數(shù)

Go 里面有三種類型的函數(shù):

  • 普通的帶有名字的函數(shù)
  • 匿名函數(shù)或者lambda函數(shù)
  • 方法(Methods)

1.普通函數(shù)

//普通函數(shù)格式
    // 入口參數(shù):parameter_list 的形式為 (param1 type1, param2 type2, …)
    // 回調(diào)參數(shù): return_value_list 的形式為 (ret1 type1, ret2 type2, …)
func functionName(parameter_list) (return_value_list) {
   …
}

//示例
func Atoi(s string) (i int, err error)
//調(diào)用
num, err := Atoi("12")

//自定義一個(gè)函數(shù)類型別名
type name func(type1,type2) type3
//示例
type binOp func(int, int) int
add := binOp
  • 左大括號 { 必須與方法的聲明放在同一行,這是編譯器的強(qiáng)制規(guī)定硬爆,大括號 {} 的使用規(guī)則在任何時(shí)候都相同。
  • 函數(shù)也是一個(gè)類型糟把,可以作為參數(shù)

2.匿名函數(shù)

func(parameter_list) (return_value_list) {...}
//示例
fplus := func(x, y int) int { return x + y }
num := fpus(1,2)
  • 匿名函數(shù)不能夠獨(dú)立存在绢涡,但可以被賦值于某個(gè)變量

3.方法

什么是面向?qū)ο缶幊趟枷耄?/a>

面向?qū)ο缶幊蹋∣OP)把對象作為程序的基本單元,一個(gè)對象包含了數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)遣疯。把程序視為一組對象的集合雄可,而每個(gè)對象都可以接收其他對象發(fā)過來的消息,并處理這些消息缠犀,程序的執(zhí)行就是一系列消息在各個(gè)對象之間傳遞数苫。

五、數(shù)組與切片

聲明數(shù)組的格式是: var identifier [n]type

把一個(gè)大數(shù)組傳遞給函數(shù)會(huì)消耗很多內(nèi)存辨液。有兩種方法可以避免這種現(xiàn)象:

  • 傳遞數(shù)組的指針
  • 使用數(shù)組的切片

切片(slice)是對數(shù)組一個(gè)連續(xù)片段的引用虐急,這個(gè)片段可以是整個(gè)數(shù)組,或者是由起始和終止索引標(biāo)識的一些項(xiàng)的子集滔迈。多個(gè)切片如果表示同一個(gè)數(shù)組的片段止吁,它們可以共享數(shù)據(jù);因此一個(gè)切片和相關(guān)數(shù)組的其他切片是共享存儲(chǔ)的燎悍。

  • 聲明切片的格式: var identifier []type赏殃,一個(gè)切片在未初始化之前默認(rèn)為 nil,長度為 0间涵。

  • 切片的初始化格式:var slice1 []type = arr1[start:end]

    • arr1[2:]arr1[2:len(arr1)] 相同,都包含了數(shù)組從第三個(gè)到最后的所有元素榜揖。

      arr1[:3]arr1[0:3] 相同勾哩,包含了從第一個(gè)到第三個(gè)元素(不包括第三個(gè))。

1.new() 和 make() 的區(qū)別

2.For-range 結(jié)構(gòu)

//這種構(gòu)建方法可以應(yīng)用于字符串(本質(zhì)是字節(jié)數(shù)組)、數(shù)組和切片
for ix, value := range slice1 {
    ...
}

3.切片的復(fù)制與追加

如果想增加切片的容量泼橘,我們必須創(chuàng)建一個(gè)新的更大的切片并把原分片的內(nèi)容都拷貝過來涝动。

//復(fù)制切片
sl_from := []int{1, 2, 3}
sl_to := make([]int, 10)
n := copy(sl_to, sl_from)

//追加切片
sl3 := []int{1, 2, 3}
sl3 = append(sl3, 4, 5, 6)

append 方法將 0 個(gè)或多個(gè)具有相同類型 s 的元素追加到切片后面并且返回新的切片

如果 s 的容量不足以存儲(chǔ)新增元素,append 會(huì)分配新的切片來保證已有切片元素和新增元素的存儲(chǔ)炬灭。

六醋粟、Map

map 是一種特殊的數(shù)據(jù)結(jié)構(gòu):一種元素對(pair)的無序集合,pair 的一個(gè)元素是 key担败,對應(yīng)的另一個(gè)元素是 value昔穴,所以這個(gè)結(jié)構(gòu)也稱為關(guān)聯(lián)數(shù)組或字典。

1.概念

1)map的聲明及初始化

var map1 map[keytype]valuetype

var mapLit map[string]int
mapLit = map[string]int{"one": 1, "two": 2}

//通過make函數(shù)初始化
var map1 = make(map[keytype]valuetype)
  • 在聲明的時(shí)候不需要知道 map 的長度提前,map 是可以動(dòng)態(tài)增長的吗货。

  • key 可以是任意可以用 == 或者 != 操作符比較的類型,比如 string狈网、int宙搬、float。

  • value 可以是任意類型

五拓哺、包(Package)

1.標(biāo)準(zhǔn)庫

fmt勇垛、os 等這樣具有常用功能的內(nèi)置包在 Go 語言中有 150 個(gè)以上。

unsafe: 包含了一些打破 Go 語言“類型安全”的命令士鸥,一般的程序中不會(huì)被使用闲孤,可用在 C/C++ 程序的調(diào)用中。

syscall-os-os/exec:

  • os: 提供一個(gè)平臺無關(guān)性的操作系統(tǒng)功能接口烤礁,采用類Unix設(shè)計(jì)讼积,隱藏了不同操作系統(tǒng)間差異,讓不同的文件系統(tǒng)和操作系統(tǒng)對象表現(xiàn)一致脚仔。
  • os/exec: 提供運(yùn)行外部操作系統(tǒng)命令和程序的方式勤众。
  • syscall: 底層的外部包,提供了操作系統(tǒng)底層調(diào)用的基本接口鲤脏。

Golang標(biāo)準(zhǔn)庫文檔

2.第三方包

golang 標(biāo)準(zhǔn)庫及第三方庫文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末们颜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子猎醇,更是在濱河造成了極大的恐慌窥突,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姑食,死亡現(xiàn)場離奇詭異波岛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)音半,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門则拷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贡蓖,“玉大人,你說我怎么就攤上這事煌茬〕馄蹋” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵坛善,是天一觀的道長晾蜘。 經(jīng)常有香客問我,道長眠屎,這世上最難降的妖魔是什么剔交? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮改衩,結(jié)果婚禮上岖常,老公的妹妹穿的比我還像新娘。我一直安慰自己葫督,他們只是感情好竭鞍,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著橄镜,像睡著了一般偎快。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上洽胶,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天晒夹,我揣著相機(jī)與錄音,去河邊找鬼姊氓。 笑死惋戏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的他膳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼绒窑,長吁一口氣:“原來是場噩夢啊……” “哼棕孙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起些膨,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蟀俊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后订雾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肢预,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年洼哎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了烫映。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沼本。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖锭沟,靈堂內(nèi)的尸體忽然破棺而出抽兆,到底是詐尸還是另有隱情,我是刑警寧澤族淮,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布辫红,位于F島的核電站,受9級特大地震影響祝辣,放射性物質(zhì)發(fā)生泄漏贴妻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一蝙斜、第九天 我趴在偏房一處隱蔽的房頂上張望名惩。 院中可真熱鬧,春花似錦乍炉、人聲如沸绢片。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽底循。三九已至,卻和暖如春槐瑞,著一層夾襖步出監(jiān)牢的瞬間吼砂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工厢洞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留飒焦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓悼沿,卻偏偏與公主長得像等舔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子糟趾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345