GO語言語法進階指南

[TOC]

GO語言語法進階指南

本筆記中沒有基礎(chǔ)語法介紹,適合學(xué)習(xí)完基礎(chǔ)語法之后,想進一步了解go語言特性的。

代碼中有很多注釋說明,會參與一些額外的知識說明

內(nèi)建方法

內(nèi)建方法,就是go語言自帶的一種方法,不需要額外的引用包。

內(nèi)建方法一般都會有使用場景,這個需要注意,多使用之后就會熟悉了。

make:

功能:創(chuàng)建 slice、map、chan,完成內(nèi)存的初始化。

說明:

  • slice和數(shù)組的區(qū)別:數(shù)組初始化內(nèi)存之后,大小固定,無法擴容,slice可以通過內(nèi)建函數(shù)進行擴容
  • chan是go語言中獨有的一種類型,叫做管道,也可以定義大小??梢酝瓿蓞f(xié)程的數(shù)據(jù)交互

返回:返回類型引用,而不是指針

package main

import "fmt"

func main() {
   // 提示,所有的內(nèi)建函數(shù)和內(nèi)建類型,可以參考源碼:builtin/builtin.go 文件
   makeSlice()
   fmt.Println("-----------------------------")
   makeMap()
   fmt.Println("-----------------------------")
   makeChan()
}

//以下為主要測試函數(shù)
// make test
func makeSlice() {
   mSlice := make([]string, 2)
   mSlice[0] = "a"
   mSlice[1] = "b"
   fmt.Println("len(mSlice):{},  cap(mSlice):{} ", len(mSlice), cap(mSlice))
   // 內(nèi)建函數(shù) append 會進行擴容
   mSlice = append(mSlice, "d")
   mSlice = append(mSlice, "e")
   mSlice = append(mSlice, "f")
   fmt.Println(mSlice)
   fmt.Println("len(mSlice):{},  cap(mSlice):{} ", len(mSlice), cap(mSlice))
}

// make map
func makeMap() {
   // interface 代表的就是value可以為int,string,這些
   mMap := make(map[string]interface{}, 3)
   mMap["a"] = 1
   mMap["b"] = "BBB"
   mMap["c"] = "CCC"
   mMap["d"] = 4
   fmt.Println(mMap)
   fmt.Println("len(mMap):{}", len(mMap))
   // map 類型無法使用 append
}

// make chan
func makeChan() {
   //管道內(nèi)的容量為3 ,可以保存 3 個 int 數(shù)據(jù)
   // 暫不講解使用方式
   mChan := make(chan int, 10)
   close(mChan)
}

new:

New 方法和make方法是有區(qū)別的

1、new出來的,內(nèi)存會置為0, make可以直接初始化指定內(nèi)存大小的對象

2、返回穿入類型的指針地址,new的類型可以任意,但是返回的只是指向這一類型的指針地址,make返回的是類型引用

func main() {
    returnType()
}

func returnType() {
    nMap := new([]string)
    mMap := make([]string, 5)

    fmt.Println("nMap type:{}", reflect.TypeOf(nMap))
    fmt.Println("mMpa type:{}", reflect.TypeOf(mMap))
    // nMap因為沒有初始化,無法使用len和cap獲取長度和容量大小,會報錯
    // fmt.Println("nMap len:{}, nMap:{}", len(nMap), cap(nMap))
    fmt.Println("mMpa len:{}, cap:{}", len(mMap), cap(mMap))
}

// 返回結(jié)果:
// nMap type:{} *[]string
// mMpa type:{} []string
// mMpa len:{}, cap:{} 5 5

append&delete:

append和delete是針對于上面兩種方式創(chuàng)建變量的一些操作的。不同操作可能要區(qū)分類型,如下:

slice -> append & copy

Map -> delete

append&copy:

append追加元素,可以進行自動擴容。

copy并不會對 目標(biāo)對象進行擴容,如果長度較小,則可能丟數(shù)據(jù)

// make test append & copy
func testAppend() {
    mSlice := make([]string, 2)
    mSlice[0] = "a"
    mSlice[1] = "b"
    fmt.Printf("len(mSlice):%d,  cap(mSlice):%d ", len(mSlice), cap(mSlice))
    // 內(nèi)建函數(shù) append 會進行擴容
    mSlice = append(mSlice, "d")
    mSlice = append(mSlice, "e")
    mSlice = append(mSlice, "f")
    fmt.Println(mSlice)
    fmt.Printf("len(mSlice):%d,  cap(mSlice):%d ", len(mSlice), cap(mSlice))
    // 使用copy 復(fù)制
    targetSlice := make([]string, 4)
    i := copy(targetSlice, mSlice)
    // targetSlice 長度就是4 ,所以就復(fù)制了4個,并沒有完全復(fù)制
    fmt.Printf("cSlice:%s, i:%d", targetSlice, i)
}

// 結(jié)果:
// len(mSlice):2,  cap(mSlice):2 [a b d e f]
// len(mSlice):5,  cap(mSlice):8 cSlice:[a b d e], i:4

Delete:

delete刪除map類型的數(shù)據(jù),格式為delete(map, key),

沒有返回數(shù)據(jù)

func deleteMap() {
    mMap := make(map[string]interface{}, 3)
    mMap["a"] = 1
    mMap["b"] = "BBB"
    mMap["c"] = "CCC"
    mMap["d"] = 4
    fmt.Println(mMap)
    fmt.Println("len(mMap):{}, mao", len(mMap))
    // 刪除存在的key
    delete(mMap, "c")
    fmt.Println(mMap)
    delete(mMap, "d")
    fmt.Println(mMap)
    // 刪除不存在的key, 沒有任何操作,也不會報錯
    delete(mMap, "c")
    fmt.Println(mMap)
}
// 結(jié)果:
// map[a:1 b:BBB c:CCC d:4]
// len(mMap):{}, mao 4
// map[a:1 b:BBB d:4]
// map[a:1 b:BBB]
// map[a:1 b:BBB]

Panic&recover:

go語言中一對異常處理組合,不同于 java或者python的 throw、try catch方式

Panic:拋出異常

Recover:捕獲異常

// ====================================Panic&recover 異常拋出和捕獲 測試===========================================
func testException() {
    // 通過defer 聲明匿名函數(shù),捕獲調(diào)用函數(shù)拋出來的異常
    // defer的使用稍后詳細(xì)補充
    // 這個匿名函數(shù)也可以拆出來,比如,defer recoverException(),在任何需要捕獲異常的地方都可以使用
    //defer func() {
    //  errInfo := recover()
    //  fmt.Println("異常信息為:", errInfo)
    //}()
    defer recoverException()
    // 會捕獲到第一個異常, 可以更換函數(shù)的位置,體驗不同的效果
    throwException03()
    throwException()
    throwException02()
}

func recoverException() {
    // Panic 拋出來的不一定是error類型,也可以是用戶自定義的一種結(jié)構(gòu)體
    reInfo := recover()
    // fmt.Println("異常信息為:", reInfo)
    // 可以對返回結(jié)果進行處理,根據(jù)recover的結(jié)果,做出判斷
    switch reInfo.(type) {
    case string:
        fmt.Println("返回字符串為:", reInfo)
    case error:
        fmt.Println("異常信息為:", reInfo)
    default:
        fmt.Println("default 信息為:", reInfo)
    }
}

// 直接拋出一個字符串
func throwException() {
    panic("a ba a ba 0101")
}
// 直接拋出一個字符串
func throwException02() {
    panic("a ba a ba 0202")
}

// 真實的拋出一個異常
func throwException03() {
    panic(errors.New("panic a error"))
    // 或者使用:panic(fmt.Errorf("panic a error")) 創(chuàng)建異常都可以
}

func main() {
    testException()
}

// 返回結(jié)果:
// 異常信息為: panic a error

Len&cap&close:

Len:變量的長度,slice、chan,string,array,map

cap:變量的容量,slice、chan、array,map無法使用,

close:關(guān)閉chan,chan比較占用資源,是協(xié)程的一個通道,使用完的時候,盡量關(guān)閉。

總結(jié):

內(nèi)建方法 功能描述 其他說明
Make() 創(chuàng)建 slice、map、chan,完成內(nèi)存的初始化。 返回類型引用,而不是指針
New() 創(chuàng)建類型變量的另外一種方式 和new的區(qū)別:<br />1、new出來的,內(nèi)存會置為0, make可以指定內(nèi)存大小<br />2、new 返回的是類型指針,不是引用
Append() append追加元素,并可以進行自動擴容。
Copy() 復(fù)制對象 copy并不會對 目標(biāo)對象進行擴容,如果長度較小,則可能丟數(shù)據(jù)
Delete() 刪除map類型指定key的數(shù)據(jù) 沒有的key進行刪除不會拋出異常
Panic() 拋出異常
Recover() 捕獲異常
Len() 變量的長度 作用在:slice、chan,string,array,map
Cap() 變量的容量 作用在:slice、chan、array,map無法使用,
Close() 關(guān)閉chan chan比較占用資源,是協(xié)程的一個通道,使用完的時候,盡量關(guān)閉。

結(jié)構(gòu)體:

若干屬性的一個集合

是面向?qū)ο蟮囊粋€體現(xiàn)

創(chuàng)建&初始化:

首先定義一個結(jié)構(gòu)體,然后創(chuàng)建一個該類型的 對象

可以直接通過var去聲明一個,或者通過new的方式創(chuàng)建該類型的一個指針

// Dog 定義dog結(jié)構(gòu)體
type Dog struct {
    // 品種
    variety string
    name    string
    color   string
}

func main() {
    // 創(chuàng)建方式 1
    var dog01 Dog
    dog01.name = "test"
    dog01.variety = "小黃狗"
    dog01.color = "yellow"
    fmt.Println("創(chuàng)建方式 1:", dog01)
    // 創(chuàng)建方式 2
    // := 這是一種語法糖,在函數(shù)內(nèi),聲明變量和賦值一起。函數(shù)外不可以使用該語法糖
    dog02 := Dog{color: "red"}
    dog02.name = "test02"
    fmt.Println("創(chuàng)建方式 2:", dog02)
    // 創(chuàng)建方式 3
    dog03 := new(Dog)
    dog03.name = "test03"
    // 三種不同的打印方式,可以觀察new出來的指針
    // 打印的結(jié)果帶有&,表示為一個指針
    fmt.Println("創(chuàng)建方式 3:", dog03)
    // 通過 * 獲取地址內(nèi)的對象,* 根據(jù)地址取值
    fmt.Println("創(chuàng)建方式 3, *dog03: ", *dog03)
    // 通過& 取地址符, 獲取地址
    fmt.Println("創(chuàng)建方式 3, &dog03:", &dog03)
}
// 打印結(jié)果:
// 創(chuàng)建方式 1: {小黃狗 test yellow}
// 創(chuàng)建方式 2: { test02 red}
// 創(chuàng)建方式 3: &{ test03 }
// 創(chuàng)建方式 3, *dog03:  { test03 }
// 創(chuàng)建方式 3, &dog03: 0xc00000e030

屬性及函數(shù):

函數(shù):必須初始化結(jié)構(gòu)體之后,才可以調(diào)用函數(shù)

作用域:通過函數(shù)名稱的大寫和小寫卻分函數(shù)的作用域,go語言中只有private和public兩種區(qū)別

備注:java中其實是有四種作用域,private、protect、public、default

結(jié)構(gòu)體中的函數(shù)聲明,并不是直接寫到結(jié)構(gòu)體中的,通過func (d *Dog)Run(){}這種形式

// Dog 定義dog結(jié)構(gòu)體
type Dog struct {
    // 品種
    variety string
    name    string
    color   string
}

func (d Dog) Run() {
    fmt.Println("the dog is running ..... ")
}
// 測試結(jié)構(gòu)體中的函數(shù)
func testStructsMethod() {
    d := Dog{}
    d.name = "小黃"
    fmt.Println(d)
    d.Run()
}

func main() {
    testStructsMethod()
}

組合:

面向?qū)ο蟮囊粋€特性就是繼承 ,go語言中是通過結(jié)構(gòu)體和結(jié)構(gòu)體的組合形式,實現(xiàn)繼承關(guān)系的。

// animal類型
type animal struct {
    id         int8
    animalType string
}

func (a animal) eat() {
    fmt.Println("Animal is eating")
}

// Dog 定義dog結(jié)構(gòu)體
type Dog struct {
    // 繼承 animal結(jié)構(gòu)體
    animal
    // 品種
    variety string
    name    string
    color   string
}

func (d Dog) Run() {
    fmt.Println("the dog is running ..... ")
}


// 測試結(jié)構(gòu)體中的函數(shù)
func testStructsMethod() {
    d := Dog{}
    d.name = "小黃"
    d.animalType = "dog"
    fmt.Println(d)
    d.Run()
    d.eat()
}

func main() {
    testStructsMethod()
}

接口

go語言可以通過接口,可以抽象、封裝和多態(tài),這些也是面向?qū)ο蟮囊恍┨卣?/p>

概念及實現(xiàn):

接口如何聲明,如何實現(xiàn)已經(jīng)聲明的這些接口

接口通過interface進行聲明的,接口的實現(xiàn)是直接針對結(jié)構(gòu)體,實現(xiàn)寫所有接口中定義的方法,即為實現(xiàn)接口,不用顯示的聲明實現(xiàn)這個接口

// Behavior
// 通過interface聲明結(jié)構(gòu)為一個接口
// 接口是一些方法的集合
type Behavior interface {
    Run() string
    Eat() string
}

type Animal struct {
    id         int8
    animalType string
}

func (a Animal) Eat() {
    fmt.Println("Animal is eating")
}

// Dog 定義dog結(jié)構(gòu)體
type Dog struct {
    // 繼承 animal結(jié)構(gòu)體
    Animal
    // 品種
    variety string
    name    string
    color   string
}

// 直接實現(xiàn)接口中定義的方法,即為實現(xiàn)接口
// 在goland中可以看到已經(jīng)有實現(xiàn)接口的標(biāo)識
func (d Dog) Eat() string {
    fmt.Println("the Animal is eating ..... ")
    return "eating"
}

func (d Dog) Run() string {
    fmt.Println("the dog is running ..... ")
    return "running"
}

func testInterface() {
    d := Dog{}
    d.name = "小黃"
    d.animalType = "dog"
    fmt.Println(d)
    fmt.Println(d.Run())
    fmt.Println(d.Eat())
}

func main() {
    testInterface()
}

多態(tài):

多態(tài)其實就是同一個接口,具有不同的實現(xiàn),便實現(xiàn)了多態(tài)

下面,Dog和Cat 的結(jié)構(gòu)體都實現(xiàn)了Behavior接口,實現(xiàn)多態(tài)的效果

還稍微使用了一下,結(jié)構(gòu)體中的標(biāo)簽,這個后面常用,這里可以做了解一下

結(jié)構(gòu)體中的大小寫,同樣具有作用域的效果,如果為小寫,json序列化的時候,可能會被忽略,無法序列化

// Behavior
// 通過interface聲明結(jié)構(gòu)為一個接口
// 接口是一些方法的集合
type Behavior interface {
    Run() string
    Eat() string
}

type Animal struct {
    id         int8
    animalType string
}

// Dog 定義dog結(jié)構(gòu)體
type Dog struct {
    // 繼承 animal結(jié)構(gòu)體
    Animal
    // 品種
    variety string
    name    string
    color   string
}

// Eat 直接實現(xiàn)接口中定義的方法,即為實現(xiàn)接口
func (d Dog) Eat() string {
    fmt.Println("the Dog is eating ..... ")
    return "eating"
}

func (d Dog) Run() string {
    fmt.Println("the Dog is running ..... ")
    return "running"
}

// Cat 定義Cat結(jié)構(gòu)體
type Cat struct {
    // 繼承 animal結(jié)構(gòu)體
    Animal
    // 品種
    variety string `default:"good"`
    // 擴展,go語言中接口體的默認(rèn)值,和結(jié)構(gòu)體序列化之后,json中的key名稱
    // 這里使用的是json,還有其他xml,ason,bson這些
    // 這也是go語言中所說的打標(biāo)簽,參考:https://juejin.cn/post/7005465902804123679
    Name  string `json:"Name" default:"橘貓"`
    color string
}

// Eat 直接實現(xiàn)接口中定義的方法,即為實現(xiàn)接口
func (c Cat) Eat() string {
    fmt.Println("the Eat is eating ..... ")
    return "eating"
}

func (c Cat) Run() string {
    fmt.Println("the Eat is running ..... ")
    return "running"
}

func testInterface() {
    d := Dog{}
    d.name = "小黃"
    d.animalType = "dog"
    fmt.Println(d)

    fmt.Println(d.Run())
    fmt.Println(d.Eat())
    fmt.Println("=============================")

    c := Cat{}
    c.color = "black"
    // 沒有序列化
    fmt.Println(c)
    result, _ := json.Marshal(c)
    // 序列化之后
    // 即使序列化之后,仍然看不到默認(rèn)值
    fmt.Println(string(result))
    fmt.Println(c.Run())
    fmt.Println(c.Eat())
}

func main() {
    testInterface()
}

總結(jié):

結(jié)構(gòu)體的聲明:interface,

結(jié)構(gòu)的實現(xiàn):直接實現(xiàn)接口中所有的方法實現(xiàn),出入?yún)⒈3忠恢?/p>

多態(tài):不同結(jié)構(gòu)體,同一實現(xiàn)一個接口的所有方法,即實現(xiàn)了多態(tài)的效果

并發(fā)

go語言的并發(fā),是通過協(xié)程實現(xiàn)的,而且go語言中的協(xié)程資源占用很小,一個協(xié)程初始化之后只有幾KB。實際的可能需要看執(zhí)行的函數(shù)內(nèi)容和其他屬性定義決定。

  • 更輕量:資源更小,幾KB,
  • 更易用:直接一個go關(guān)鍵字就可以開啟一個協(xié)程,go run()即可
  • 更便捷:更容易嵌入其他程序中,沒有java或者python中的進程或者協(xié)程那么繁瑣

多協(xié)程通信:chan管道通信,chan可以實現(xiàn)信號和信號量的效果

多協(xié)程同步:協(xié)程A在處理某個數(shù)據(jù),協(xié)程B不應(yīng)該在A操作過程中,對數(shù)據(jù)做處理,否則會讓A獲取到臟數(shù)據(jù)。java 和python會使用鎖機制,go語言中也可以使用多協(xié)程同步,實現(xiàn)鎖的機制。特別是針對于大數(shù)據(jù)的處理。

協(xié)程:

默認(rèn)go語言使用的協(xié)程,占用的是所有的CPU核心數(shù)。

一般會使用代碼限制協(xié)程占用CPU的核心數(shù),默認(rèn)留出一個核心,給系統(tǒng)或者其他調(diào)度服務(wù)

  1. 協(xié)程在執(zhí)行期間,主進程停止之后,會停止正在運行中的協(xié)程
  2. runtime.GOMAXPROCS( n int )進行設(shè)置使用CPU核心數(shù)
  3. runtime.NumCPU() 獲取服務(wù)器CPU核心數(shù)
// 循環(huán)測試函數(shù)
func goLoopTest01() {
    for i := 0; i < 20; i++ {
        time.Sleep(1 * time.Second)
        fmt.Println("goLoopTest01 goLoop : ", i)
    }
}

// 循環(huán)測試函數(shù) 02
func goLoopTest02() {
    for i := 0; i < 20; i++ {
        time.Sleep(1 * time.Second)
        fmt.Println("goLoopTest02 goLoop  : ", i)
    }
}

func main() {
    // 獲取服務(wù)器CPU核心數(shù)
    cpu := runtime.NumCPU()
    fmt.Println("服務(wù)器CPU核心數(shù)為: ", cpu)
    // 限制協(xié)程運行的核心數(shù),2個CPU核心
    runtime.GOMAXPROCS(2)
    // 這樣運行過快,main結(jié)束,則協(xié)程也會被關(guān)閉,需要額外注意
    go goLoopTest01()
    go goLoopTest02()
    // 這樣等待10秒,兩個協(xié)程打印,但是不可能等待所有打印出來
    time.Sleep(10 * time.Second)
    fmt.Println("main函數(shù)執(zhí)行結(jié)束")
}

協(xié)程通信:

協(xié)程之間的通信和同步,都是通過管道chan接受和發(fā)送數(shù)據(jù)。

一般也會通過select配合使用,不停的獲取數(shù)據(jù)。

// 聲明一個管道,和聲明管道內(nèi)部數(shù)據(jù)類型
var channel chan int = make(chan int, 10)
var channel02 chan int = make(chan int, 10)

// Send 發(fā)送數(shù)據(jù)
func Send() {
    channel <- 1
    channel <- 2
    channel <- 3
    time.Sleep(2 * time.Second)
    channel <- 4
    channel <- 5
}

// Receive 接收管道里的數(shù)據(jù)
func Receive() {
    num := <-channel
    fmt.Println(num)
    for {
        // select 會不停的獲取管道的數(shù)據(jù)
        select {
        // case 可以寫多個,從不同的管道中獲取
        case num := <-channel:
            fmt.Println("管道channel獲取到的數(shù)據(jù) : ", num)
            // 寫多個
        case num02 := <-channel02:
            fmt.Println("管道channel02獲取到的數(shù)據(jù) : ", num02)
        }
    }
}

func main() {
    go Send()
    go Receive()
    time.Sleep(10 * time.Second)

協(xié)程同步:

系統(tǒng)工具:sync.WaitGroup{} ,可以實現(xiàn)多協(xié)程的同步,比如:讀寫的操作,要等寫完之后,才可以讀取

add(delta int):添加協(xié)程記錄

Done():移除協(xié)程記錄

Wait():同步等待所有記錄的協(xié)程記錄全部結(jié)束

說明:所有add和done的次數(shù)必須一致,否則可能導(dǎo)致一直等待

var WG = sync.WaitGroup{}

func Read() {
    // 添加讀者
    for i := 0; i < 3; i++ {
        fmt.Println("Read WG add 1")
        WG.Add(1)
    }
}

func Write() {
    // 等待一個讀者 完畢,WG減少一個
    for i := 0; i < 3; i++ {
        fmt.Println("Write WG done 1")
        time.Sleep(1 * time.Second)
        WG.Done()
    }
}

func main() {
    // 主進程內(nèi),讀取
    Read()
    // 開啟協(xié)程 寫入數(shù)據(jù)
    go Write()
    // 等待所有協(xié)程執(zhí)行完畢
    WG.Wait()
    fmt.Println("all gorotine done....")
}

總結(jié):

知識點 描述
如何啟動一個協(xié)程 關(guān)鍵字go直接啟動
CPU核心數(shù)使用的設(shè)置 runtime.GOMAXPROCS( n int )進行設(shè)置使用CPU核心數(shù) <br />runtime.NumCPU() 獲取服務(wù)器CPU核心數(shù)
協(xié)程之間的通信 類型chan進行通信,配合select進行循環(huán)獲取
如何控制協(xié)程之間的同步 sync.WaitGroup{} 控制協(xié)程同步。具有add,done,waite方法

指針

指針的操作,主要包括:

  • 基本使用
  • 指針數(shù)組
  • 指向指針的指針
  • 值傳遞和指針傳遞

指針基本使用:

定義指針變量

為指針變量賦值

訪問指針變量中指向地址的值

go語言不支持指針的運算

// & 取地址,獲取某個變量的地址
// * 指針運算符,表示一個變量是指針類型,也可以表示一個指針變量所指向的存儲單元, 也就是這個地址所存儲的值.
func main() {
    var count int = 20
    var countPoint *int
    var countPoint01 *int
    // & 取地址,獲取某個變量的地址
    // * 指針運算符,表示一個變量是指針類型,也可以表示一個指針變量所指向的存儲單元, 也就是這個地址所存儲的值.
    countPoint = &count
    fmt.Println(countPoint)
    // count 和 countPoint 地址一樣
    fmt.Printf("Count 地址:%x,CountPoint 地址: %x, CountPoint 內(nèi)容:%d ", &count, countPoint, *countPoint)
    // countPoint01 地址,是空的
    fmt.Println("countPoint01 地址是:", countPoint01)
}

指針數(shù)組&數(shù)組指針:

func TestPointArray() {
    // 指針數(shù)組:一個數(shù)組里面保存的都是對象的指針
    // 數(shù)組指針:一個指向數(shù)組的指針
    // 創(chuàng)建變量
    a, b, c := 1, 2, 3
    //指針數(shù)組
    pointArr := [...]*int{&a, &b, &c}
    fmt.Println("指針數(shù)組, point Arr: ", pointArr)
    // 數(shù)組指針
    arr := [...]int{1, 2, 3}
    arrPoint := &arr
    fmt.Println("數(shù)組指針地址:", arrPoint)
}

func main() {
    TestPointArray()
}

JSON

go語言主要是通過encoding/json 進行序列化和反序列化的。

序列化:將對象和結(jié)構(gòu)體,變?yōu)閖son格式,json.Marshal(v interface{}) ([]byte, error)

  • 結(jié)構(gòu)體的序列化
  • Map的序列化

反序列化:將json格式變?yōu)閷ο?,json.Unmarshal(data []byte, v interface{}) error

Tag:在go語言中,叫標(biāo)簽,有點類似java中的注解。寫在結(jié)構(gòu)體的后面,在序列化的時候,可以作為json中的key,反序列化的時候也作為一個映射。

json序列化:

type Server struct {
    ServerName string
    ServerIP   string
    ServerPort int
}

func Serialize() {
    // 創(chuàng)建一個server
    // 也可以這樣創(chuàng)建 : server:= Server{ServerIP: "10.0.0.1", ServerName: "JsonTest", ServerPort: 8888}
    // new出來的是一個指針類型
    server := new(Server)
    server.ServerIP = "10.0.0.1"
    server.ServerName = "JsonTest"
    server.ServerPort = 8080
    // 打印原有的對象,指針的指針,才是指針原有地址的內(nèi)容
    fmt.Println("server : ", *server)
    // 打印序列化之后的
    serverJson, err := json.Marshal(server)
    if err != nil {
        fmt.Println("序列化出現(xiàn)異常,異常信息為: ", err.Error())
    }
    fmt.Println("ServerJson is ", string(serverJson))

    // 序列化map類型
    serverMap := make(map[string]interface{})
    serverMap["ServerIP"] = "10.0.0.1"
    serverMap["ServerName"] = "JsonTestMap"
    serverMap["ServerPort"] = 8080
    m := make(map[string]string)
    m["test"] = "test"
    serverMap["ServerDetail"] = m
    resultMap, _ := json.Marshal(serverMap)
    fmt.Println("map序列化之后為:", string(resultMap))
}

func main() {
    Serialize()
}

json反序列化:

反序列化,就是將json轉(zhuǎn)換為對應(yīng)的結(jié)構(gòu)體或者map,是上面的反向操作,這個就不在演示

json.Unmarshal(data []byte, v interface{}) error

語法糖

語法糖:增加語言的可讀性和實用性,對語言原有邏輯并不造成任何影響

go語言中的語法糖:

  • ... 可變參數(shù)
  • := 聲明、賦值、類型推斷
func Candy(values ...string) {
    for i, value := range values {
        fmt.Printf("%d 個元素是%s \n", i, value)
    }
}

func CandyTest() {
    // := 聲明變量,并推斷變量類型,作用在方法內(nèi)
    values := make([]string, 5)
    values = append(values, "test01", "test02", "test03", "test04")
    // 打印類型
    fmt.Println(reflect.TypeOf(values))
    // Candy函數(shù)中可以追加任意個數(shù)的參數(shù), 但是類型都應(yīng)該是字符串
    Candy("test01", "test02", "test03", "test04")
}

func main() {
    CandyTest()
}

Module介紹

Module介紹:

Go module 是go語言的一個包管理,類似于java的maven,python的pip 對引用的包的版本等管理。

這些命令還是希望多動手去敲,去使用。

命令 功能說明 備注
go mod init 初始化項目,使用go module 進行包管理,會生成go.mod和go.sum文件
go mod graph 可視化go項目包依賴的關(guān)系 graphviz,echart也可以實現(xiàn)
go mod download 下載某個依賴包 go get
go mod tidy 會檢測該文件夾目錄下所有引入的依賴,寫入 go.mod 文件<br />下載需要的依賴,刪除無用的依賴
go mod verify 校驗?zāi)硞€安裝包,在go.mod文件中會記錄文件的MD5
go mod why 查看為什么會依賴某一個包
go mod edit 編輯go.mod,添加或者刪除依賴
go mod vendor 將依賴下載到當(dāng)前項目vendor包下,實現(xiàn)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容