網(wǎng)站首頁 編程語言 正文
一、Go 語言兩大數(shù)據(jù)類型
Go 語言數(shù)據(jù)類型包含基礎(chǔ)類型和復(fù)合類型兩大類。
基礎(chǔ)類型包括:
- 布爾類型 bool。
- 數(shù)值類型 int,int8,int16,int32,int64,float32,float64。
- uint8,uint16,uint32,uint64。
- 字符串 string,byte,rune。
復(fù)合類型包括:
- 指針、數(shù)組、切片、字典、通道、結(jié)構(gòu)體、接口。
下面用代碼加注釋的方式說明:
二、基礎(chǔ)類型
聲明一個bool類型的變量,只有true和false兩個值,初始值為false?? ?
var isLogin bool ?? ? // 聲明一個int類型的變量,初始值為0 //(int8,int16,int32 uint8,uint16....類似,只是有符號和無符號的區(qū)別) // 最常用的就是int,如果需要更大的范圍可以用int64或者uint64 var count int ?? ??? ? // 聲明一個string類型的變量,初始值為"" var s string ?? ??? ? //聲明一個byte類型的變量 var b byte ?? ? //聲明一個rune類型的變量 //int32的別名,表示單個Unicode字符 var r rune
三、復(fù)合類型
指針
go的指針和c語言的指針類型,都是表示一個變量的地址,不同的是,go的指針要比c的指針簡單的多,老規(guī)矩,代碼注釋,如下:
package main import "fmt" func main() { ?? ? ? ? var count = 100 //定義變量count ?? ? ? ? var ptr *int ?? ?//定義一個指針ptr,此指針可以保存int類型變量的地址 ? ? ptr = &count?? ?//ptr保存的是變量count的地址, & 符號是取變量地址的符號 ?? ? ? ? fmt.Println("count=",count) //打印count的值 ? ? fmt.Println("ptr=", *ptr)?? ?//打印ptr指向的變量的值,此句打印100 }
運行結(jié)果如下:
count= 100
ptr= 100
四、數(shù)組(array)
數(shù)組為一組相同數(shù)據(jù)類型數(shù)據(jù)的集合,大小固定,不能更改,每個元素稱為element,聲明的數(shù)組元素默認值都是對應(yīng)類型的0值。而且數(shù)組在Go語言中是一個值類型(value type)所有值類型變量在賦值和作為參數(shù)傳遞時都會產(chǎn)生一次復(fù)制動作,即對原值的拷貝
package main import "fmt" func main() { ?? ? ?? ?// 1.聲明后賦值 ?(var <數(shù)組名稱> [<數(shù)組長度>]<數(shù)組元素>) ?? ?var arr [2]int ? // 數(shù)組元素的默認值都是 0 ?? ?fmt.Println(arr) // 輸出:[0 0] ?? ?arr[0] = 1 ?? ?arr[1] = 2 ?? ?fmt.Println(arr) // 輸出:[1 2] ?? ? ?? ?// 2.聲明并賦值 (var <數(shù)組名稱> = [<數(shù)組長度>]<數(shù)組元素>{元素1,元素2,...}) ?? ?var intArr = [2]int{1, 2} ?? ?strArr := [3]string{`aa`, `bb`, `cc`} ?? ?fmt.Println(intArr) // 輸出:[1 2] ?? ?fmt.Println(strArr) // 輸出:[aa bb cc] ?? ? ?? ?// 3.聲明時不設(shè)定大小,賦值后語言本身會計算數(shù)組大小 ?? ?// var <數(shù)組名稱> [<數(shù)組長度>]<數(shù)組元素> = [...]<元素類型>{元素1,元素2,...} ?? ?var arr1 = [...]int{1, 2} ?? ?arr2 := [...]int{1, 2, 3} ?? ?fmt.Println(arr1) // 輸出:[1 2] ?? ?fmt.Println(arr2) // 輸出:[1 2 3] ?? ?//arr1[2] = 3 // 編譯報錯,數(shù)組大小已設(shè)定為2 ?? ? ?? ?// 4.聲明時不設(shè)定大小,賦值時指定索引 ?? ?// var <數(shù)組名稱> [<數(shù)組長度>]<數(shù)組元素> = [...]<元素類型>{索引1:元素1,索引2:元素2,...} ?? ?var arr3 = [...]int{1: 22, 0: 11, 2: 33} ?? ?arr4 := [...]string{2: "cc", 1: "bb", 0: "aa"} ?? ?fmt.Println(arr3) // 輸出:[11 22 33] ?? ?fmt.Println(arr4) // 輸出:[aa bb cc] ?? ? ?? ?// 遍歷數(shù)組 ?? ?for i := 0; i < len(arr4); i++ { ?? ??? ?v := arr4[i] ?? ??? ?fmt.Printf("i:%d, value:%s\n", i, v) ?? ?} }
五、切片(slice)
因為數(shù)組的長度定義后不可修改,所以需要切片來處理可變長數(shù)組數(shù)據(jù)。切片可以看作是一個可變長的數(shù)組,是一個引用類型。
它包含三個數(shù)據(jù):
- 指向原生數(shù)組的指針
- 切片中的元素個數(shù)
- 切片已分配的存儲空間大小
注:了解c++和java的同學(xué),可以參考vector和List,切片就是類似這兩個數(shù)據(jù)結(jié)構(gòu),直接上代碼:
package main import "fmt" func main() { ? ? var sl []int ? ? ? ? ? ? // 聲明一個切片 ? ? sl = append(sl, 1, 2, 3) // 往切片中追加值 ? ? fmt.Println(sl) ? ? ? ? ?// 輸出:[1 2 3] ? ? var arr = [5]int{1, 2, 3, 4, 5} // 初始化一個數(shù)組 ? ? var sl1 = arr[0:2] ? ? ? ? ? ? ?// 冒號:左邊為起始位(包含起始位數(shù)據(jù)),右邊為結(jié)束位(不包含結(jié)束位數(shù)據(jù));不填則默認為頭或尾 ? ? var sl2 = arr[3:] ? ? var sl3 = arr[:5] ? ? fmt.Println(sl1) // 輸出:[1 2] ? ? fmt.Println(sl2) // 輸出:[4 5] ? ? fmt.Println(sl3) // 輸出:[1 2 3 4 5] ? ? sl1 = append(sl1, 11, 22) // 追加元素 ? ? fmt.Println(sl1) ? ? ? ? ?// 輸出:[1 2 11 22] }
使用make關(guān)鍵字直接創(chuàng)建切片,
語法:make([]類型, 大小,預(yù)留空間大小),make() 函數(shù)用于聲明slice切片、map字典、channel通道。
如下:
package main import "fmt" func main() { ?? ?var s1 = make([]int, 5) ? ? ? ? ?// 定義元素個數(shù)為5的切片 ?? ?s2 := make([]int, 5, 10) ? ? ? ? // 定義元素個數(shù)5的切片,并預(yù)留10個元素的存儲空間(預(yù)留空間不知道有什么用?) ?? ?s3 := []string{`aa`, `bb`, `cc`} // 直接創(chuàng)建并初始化包含3個元素的數(shù)組切片 ?? ? ?? ?fmt.Println(s1, len(s1)) // 輸出:[0 0 0 0 0] 5 ?? ?fmt.Println(s2, len(s2)) // 輸出:[0 0 0 0 0] 5 ?? ?fmt.Println(s3, len(s3)) // [aa bb cc] 3 ?? ? ?? ?s1[1] = 1 // 聲明或初始化大小中的數(shù)據(jù),可以指定賦值 ?? ?s1[4] = 4 ?? ?//s1[5] = 5 // 編譯報錯,超出定義大小 ?? ?s1 = append(s1, 5) ? ? ? // 可以追加元素 ?? ?fmt.Println(s1, len(s1)) // 輸出:[0 1 0 0 4 5] 6 ?? ? ?? ?s2[1] = 1 ?? ?s2 = append(s2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) ?? ?fmt.Println(s2, len(s2)) // 輸出:[0 1 0 0 0 1 2 3 4 5 6 7 8 9 10 11] 16 ?? ? ?? ?// 遍歷切片 ?? ?for i := 0; i < len(s2); i++ { ?? ??? ?v := s2[i] ?? ??? ?fmt.Printf("i: %d, value:%d \n", i, v) ?? ?} }
六、字典/映射(map)
map
是一種鍵值對的無序集合,與 slice
類似也是一個引用類型。map 本身其實是個指針,指向內(nèi)存中的某個空間。
聲明方式與數(shù)組類似,聲明方式:var 變量名 map[key類型值類型 或直接使用 make 函數(shù)初始化:make(map[key類型]值類型, 初始空間大小)。
其中key值可以是任何可以用==判斷的值類型,對應(yīng)的值類型沒有要求。
直接上代碼,如下:
package main import ( ? ? "fmt" ? ? "unsafe" ) func main() { ? ? // 聲明后賦值 ? ? var m map[int]string ? ? fmt.Println(m) // 輸出空的map:map[] ? ? //m[1] = `aa` ? ?// 向未初始化的map中賦值報錯:panic: assignment to entry in nil map ? ? // 聲明并初始化,初始化使用{} 或 make 函數(shù)(創(chuàng)建類型并分配空間) ? ? var m1 = map[string]int{} ? ? var m2 = make(map[string]int) ? ? m1[`a`] = 11 ? ? m2[`b`] = 22 ? ? fmt.Println(m1) // 輸出:map[a:11] ? ? fmt.Println(m2) // 輸出:map[b:22] ? ? // 初始化多個值 ? ? var m3 = map[string]string{"a": "aaa", "b": "bbb"} ? ? m3["c"] = "ccc" ? ? fmt.Println(m3) // 輸出:map[a:aaa b:bbb c:ccc] ? ? // 刪除 map 中的值 ? ? delete(m3, "a") // 刪除鍵 a 對應(yīng)的值 ? ? fmt.Println(m3) // 輸出:map[b:bbb c:ccc] ? ? // 查找 map 中的元素 ? ? v, ok := m3["b"] ? ? if ok { ? ? ? ? fmt.Println(ok) ? ? ? ? fmt.Println("m3中b的值為:", v) // 輸出:m3中b的值為: bbb ? ? } ? ? // 或者 ? ? if v, ok := m3["b"]; ok { // 流程處理后面講 ? ? ? ? fmt.Println("m3中b的值為:", v) // 輸出:m3中b的值為: bbb ? ? } ? ? fmt.Println(m3["c"]) // 直接取值,輸出:ccc ? ? // map 中的值可以是任意類型 ? ? m4 := make(map[string][5]int) ? ? m4["a"] = [5]int{1, 2, 3, 4, 5} ? ? m4["b"] = [5]int{11, 22, 33} ? ? fmt.Println(m4) ? ? ? ? ? ? ? ?// 輸出:map[a:[1 2 3 4 5] b:[11 22 33 0 0]] ? ? fmt.Println(unsafe.Sizeof(m4)) // 輸出:8,為8個字節(jié),map其實是個指針,指向某個內(nèi)存空間 }
七、通道(channel)
說到通道 channel
,則必須先了解下 Go 語言的 goroutine
協(xié)程(輕量級線程)。channel就是為 goroutine 間通信提供通道。goroutine
是 Go 語言提供的語言級的協(xié)程,是對 CPU 線程和調(diào)度器的一套封裝。
channel
也是類型相關(guān)的,一個 channel 只能傳遞一種類型的值。
聲明:var 通道名 chan 通道傳遞值類型 或 make 函數(shù)初始化:make(chan 值類型, 初始存儲空間大小)
說白了,通道類似消息隊列,主要應(yīng)用在并發(fā)編程里面比較多,
直接上代碼,如下:
package main import ( ? ? "fmt" ? ? "time" ) func main() { ? ? var ch1 chan int ? ? ? ? ? ?// 聲明一個通道 ? ? ch1 = make(chan int) ? ? ? ?// 未初始化的通道不能存儲數(shù)據(jù),初始化一個通道 ? ? ch2 := make(chan string, 2) // 聲明并初始化一個帶緩沖空間的通道 ? ? // 通過匿名函數(shù)向通道中寫入數(shù)據(jù),通過 <- 方式寫入 ? ? go func() { ch1 <- 1 }() ? ? go func() { ch2 <- `a` }() ? ? v1 := <-ch1 // 從通道中讀取數(shù)據(jù) ? ? v2 := <-ch2 ? ? fmt.Println(v1) // 輸出:1 ? ? fmt.Println(v2) // 輸出:a ? ? // 寫入,讀取通道數(shù)據(jù) ? ? ch3 := make(chan int, 1) // 初始化一個帶緩沖空間的通道 ? ? go readFromChannel(ch3) ? ? go writeToChannel(ch3) ? ? // 主線程休眠1秒,讓出執(zhí)行權(quán)限給子 Go 程,即通過 go 開啟的 goroutine,不然主程序會直接結(jié)束 ? ? time.Sleep(1 * time.Second) } func writeToChannel(ch chan int) { ? ? for i := 1; i < 10; i++ { ? ? ? ? fmt.Println("寫入:", i) ? ? ? ? ch <- i ? ? } } func readFromChannel(ch chan int) { ? ? for i := 1; i < 10; i++ { ? ? ? ? v := <-ch ? ? ? ? fmt.Println("讀?。?, v) ? ? } }
運行結(jié)果如下:
// ------ ?輸出:--------
1
a
寫入: 1
寫入: 2
寫入: 3
讀取: 1
讀?。?2
讀?。?3
寫入: 4
寫入: 5
寫入: 6
讀取: 4
讀?。?5
讀?。?6
寫入: 7
寫入: 8
寫入: 9
讀?。?7
讀取: 8
讀取: 9
goroutine
和 channel
的詳細用法會有相應(yīng)的博客專門來講這一章節(jié),具體可在我的個人主頁里面,找一下相關(guān)的博客參考。
八、結(jié)構(gòu)體(struct)
結(jié)構(gòu)體是一種聚合的數(shù)據(jù)類型,是由零個或多個任意類型的值聚合成的實體。每個值稱為結(jié)構(gòu)體的成員,和java中的class是一個意思:
package main import "fmt" // 定義一個結(jié)構(gòu)體 person type person struct { ? ? name string ? ? age ?int } func main() { ? ? var p person ? // 聲明一個 person 類型變量 p ? ? p.name = "max" // 賦值 ? ? p.age = 12 ? ? fmt.Println(p) // 輸出:{max 12} ? ? p1 := person{name: "mike", age: 10} // 直接初始化一個 person ? ? fmt.Println(p1.name) ? ? ? ? ? ? ? ?// 輸出:mike ? ? p2 := new(person) // new函數(shù)分配一個指針,指向 person 類型數(shù)據(jù) ? ? p2.name = `張三` ? ? p2.age = 15 ? ? fmt.Println(*p2) // 輸出:{張三 15} }
九、接口(interface)
接口用來定義行為。Go 語言不同于面向?qū)ο笳Z言,沒有類的概念,也沒有傳統(tǒng)意義上的繼承。Go 語言中的接口,用來定義一個或一組行為,某些對象實現(xiàn)了接口定義的行為,則稱這些對象實現(xiàn)了(implement)該接口,類型即為該接口類型。
定義接口也是使用 type 關(guān)鍵字,格式為:
// 定義一個接口 type InterfaceName interface { ? ? FuncName1(paramList) returnType ? ? FuncName2(paramList) returnType ? ? ... }
實列:
package main import ( ? ? "fmt" ? ? "strconv" ) // 定義一個 Person 接口 type Person interface { ? ? Say(s string) string ? ? Walk(s string) string } // 定義一個 Man 結(jié)構(gòu)體 type Man struct { ? ? Name string ? ? Age ?int } // Man 實現(xiàn) Say 方法 func (m Man) Say(s string) string { ? ? return s + ", my name is " + m.Name } // Man 實現(xiàn) Walk 方法,strconv.Itoa() 數(shù)字轉(zhuǎn)字符串 func (m Man) Walk(s string) string { ? ? return "Age: " + strconv.Itoa(m.Age) + " and " + s } func main() { ? ? var m Man ? ? ? // 聲明一個類型為 Man 的變量 ? ? m.Name = "Mike" // 賦值 ? ? m.Age = 30 ? ? fmt.Println(m.Say("hello")) ? ?// 輸出:hello, my name is Mike ? ? fmt.Println(m.Walk("go work")) // 輸出:Age: 30 and go work ? ? jack := Man{Name: "jack", Age: 25} // 初始化一個 Man 類型數(shù)據(jù) ? ? fmt.Println(jack.Age) ? ? fmt.Println(jack.Say("hi")) // 輸出:hi, my name is jack }
十、錯誤(error)
error 類型本身是 Go 語言內(nèi)部定義好的一個接口,接口里定義了一個 Error() 打印錯誤信息的方法,源碼如下:
type error interface { ? ? Error() string }
自定義錯誤信息:
package main import ( ? ? "errors" ? ? "fmt" ) func main() { ? ? // 使用 errors 定制錯誤信息 ? ? var e error ? ? e = errors.New("This is a test error") ? ? fmt.Println(e.Error()) // 輸出:This is a test error ? ? // 使用 fmt.Errorf() 定制錯誤信息 ? ? err := fmt.Errorf("This is another error") ? ? fmt.Println(err) // 輸出:This is another test error }
原文鏈接:https://blog.csdn.net/weixin_46931877/article/details/122408821
相關(guān)推薦
- 2023-07-06 golang中time包時間處理
- 2022-11-22 Kotlin?List與Set和Map實例講解_Android
- 2021-12-10 golang?db事務(wù)的統(tǒng)一封裝的實現(xiàn)_Golang
- 2022-12-21 redis保存AtomicInteger對象踩坑及解決_Redis
- 2022-07-13 CSS 不需要清除浮動的圣杯布局~面試可能會問
- 2023-12-24 http中的get和post方法的區(qū)別
- 2022-12-22 Flutter組件開發(fā)過程完整講解_Android
- 2022-07-26 圖解Elasticsearch 獲取兩個索引數(shù)據(jù)不同之處的四種方案
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支