[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©:
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ù)
- 協(xié)程在執(zhí)行期間,主進程停止之后,會停止正在運行中的協(xié)程
- runtime.GOMAXPROCS( n int )進行設(shè)置使用CPU核心數(shù)
- 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) | |