Go語言中文文檔-1Go基礎


Go於2009年由谷歌推出。

Init函數和main函數

Init函數

用於程序執行前初始化包變量
每個包可以多個,同一個包多個init執行順序無明確定義
按照包導入依賴關系決定不同包初始化函數執行順序
不能被調用,main函數執行前自動被調用

與main函數異同

相同點:
都不能有參數和返回值,都是go程序自動調用。
不同點:
init可以用於不同包,可定義多個。
main只能用於main包,只能定義一個。

命令

go env打印Go語言環境
go run編譯運行命令源碼文件
go get從互聯網下載代碼包依賴包編譯和安裝
go build編譯源碼文件、代碼包及依賴包
go install編譯並安裝代碼包及依賴包
go doc + Go實體 查看文檔
go test測試go編寫的程序
go list列出代碼包信息

運算符

自增自減不是運算符

下划線

下划線在import中

import _ "./hello"
表示程序引用包中所有init函數,並不能通過包名調用包中其他函數。

下划線在代碼中

表示忽略這個變量,如果用變量不使用,編譯器報錯。

變量和常量

變量

變量聲明后必須使用
標准聲明:var name string
批量聲明:var (
a string
b int
c bool
d float32
)
類型推導: var sex = 1
函數內部短變量聲明:n := 100
匿名變量:x, _ = foo()不占命名空間,不分配內存

常量

const pi = 3.1415

const (
a = 1
b
)
上述b == a

iota
常量計數器,只能在常量表達式使用。

基本類型

整型

int64對應C語言long

多行字符串

定義時必須使用反引號字符

字符串常用操作

分割:strings.Split
判斷是否包含:strings.Contains
前后綴判斷:strings.HasPrefix, strings.HasSuffix
子串位置:strings.Index(), strings.LastIndex()
join操作:strings.Join(a[]string, sep string)

byte rune

byte: ASCII類型
rune:UTF-8

修改字符串

先轉換成[]rune, []byte完成后再轉換為string

類型轉換

go只有強制類型轉換,無隱式類型轉換

數組Array

var a[5] int和var a [10]int是不同類型
指針數組 [n]* T, 數組指針 *[]T
數組初始化:var arr = [...]int{1, 2, 3, 4, 5, 6}
var arr1 = [5]int{2: 100, 4: 200}
var arr2 = [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
len, cap都返回數組長度。

切片Slice

切片是引用類型,自身是結構體,值拷貝傳遞。
創建切片:var s1 []int
s2 := []int{1, 2, 3}
var s3 []int = make([]int, len, cap)省略cap則cap = len
s1 := []int{0, 1, 2, 3, 8:100}
data := [][]int{
[]int{1, 2, 3},
[]int{100, 200},
[]int{11, 22, 33, 44},
}
d := [5]struct {
x int
}{}
c = append(s1, s2...)
超出slice.cap限制,就會重新分配底層數組。通常兩倍容量重新分配。
數組或切片轉字符串: strings.Replace(strings.Trim(fmt.Sprint(array_or_slice), "[]"), " ", ",", -1)

slice底層實現

切片數據結構

切片通過指針引用底層數組,切片是只讀對象,是對類似數組指針的封裝。

空切片和nil切片

空切片:var slice []int一般表示一個空集合
nil切片:slice := make([]int, 0)函數發生異常時返回
slice := []int{}
上述區別,一個指針指向內存地址,一個指針為nil

擴容策略

如果切片容量小於1024,兩被擴容到新地址,不改變原數組
如果切片容量超過1024,1.25倍擴容
擴容針對原來容量,不針對原數組長度。

指針

Go指針不能偏移與運算

new和make

Go語言對引用類型變量,使用時要為之分配內存,對值類型,使用時默認分配好了內存空間。

new

a := new(int)
指針作為引用類型,聲明后必須用new初始化后才可以為指針指向的值賦值。

make

使用slice、map、channel時,都需要使用make進行初始化。

new、make區別

make返回引用類型本身, new返回指向類型的指針。
make用於slice、map、channel初始化,而new用於類型內存分配

Map

map是無序的kv數據結構,是引用類型,初始化后可以使用。
定義: map[KeyType]ValueType
分配內存:make(map[KeyType]ValueType, [cap])
判斷某個鍵是否存在:value, ok := map[key]
if ok {
} else {
}
遍歷:for k, v := range m {
}
for k := range m {
}
遍歷順序不一定是添加順序
刪除鍵值對:delete(m, key)

Go中Map的實現原理

通過桶的方式解決沖突問題,key,value分開存儲以節省內存空間,每個桶存放元素有最大數量,超過最大數量則通過overflow獲取鏈表上的下一個桶。

結構體

自定義類型:
type MyInt int
類型別名:
type byte = uint8
自定義類型和類型別名的區別
自定義類型后通過新類型定義變量,輸出變量類型為新類型。
類型別名后,仍然輸出原類型。
匿名結構體:
var user struct{Name string; Age int}
創建指針類型結構體:
var p2 = new(person)
取結構體的地址實例化
p3 := &person{}
使用值的列表初始化:
p8 := &person {
1,
"aa",
}
上述方式必須初始化所有字段,必須與聲明方式一致,不能和鍵值初始化混用。

構造函數

func newPerson(name, city string, age int8) *person {
return &person{
name: name,
city: city,
age: age,
}
}
p9 := newPerson("pprof.cn", "測試", 90)

方法和接收者

方法:作用於特定類型變量的函數
方法屬於特定的類型,函數不屬於任何類型。
什么時候應該使用指針類型接收者?
需修改接受者值,接受者拷貝代價高,方法使用的接受者一致性(如都是指針接受者)。

Go中任意類型都可以擁有方法,但我們不能給別的包的類型定義方法。

結構體字段的可見性

結構體中字段大寫開頭表示可公開訪問,小寫表示僅在當前結構體包中訪問。

結構體與JSON序列化

序列化
data, err := json.Marshal(c)
反序列化
err = json.Unmarshal([]byte(str), c1)

結構化標簽

Tag: 結構體的元信息
key1:"value1" key2:"value2"

實現map有序輸出

點擊查看代碼
package main

import (
    "fmt"
    "sort"
)

func main() {
    map1 := make(map[int]string, 5)
    map1[1] = "www.topgoer.com"
    map1[2] = "rpc.topgoer.com"
    map1[5] = "ceshi"
    map1[3] = "xiaohong"
    map1[4] = "xiaohuang"
    sli := []int{}
    for k, _ := range map1 {
        sli = append(sli, k)
    }
    sort.Ints(sli)
    for i := 0; i < len(map1); i++ {
        fmt.Println(map1[sli[i]])
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM