欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言數(shù)據(jù)類型詳細介紹

 更新時間:2022年03月31日 09:53:56   作者:蘇州程序大白  
這篇文章主要介紹了Go語言數(shù)據(jù)類型詳細介紹,Go語言數(shù)據(jù)類型包含基礎類型和復合類型兩大類,下文關于這兩類型的相關介紹,需要的小伙伴可以參考一下

一、Go 語言兩大數(shù)據(jù)類型

Go 語言數(shù)據(jù)類型包含基礎類型和復合類型兩大類。

基礎類型包括:

  • 布爾類型 bool。
  • 數(shù)值類型 int,int8,int16,int32,int64,float32,float64。
  • uint8,uint16,uint32,uint64。
  • 字符串 string,byte,rune。

復合類型包括:

  • 指針、數(shù)組、切片、字典、通道、結構體、接口。

下面用代碼加注釋的方式說明:

二、基礎類型

聲明一個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

三、復合類型

指針

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
}

運行結果如下:

count= 100
ptr= 100

四、數(shù)組(array)

數(shù)組為一組相同數(shù)據(jù)類型數(shù)據(jù)的集合,大小固定,不能更改,每個元素稱為element,聲明的數(shù)組元素默認值都是對應類型的0值。而且數(shù)組在Go語言中是一個值類型(value type)所有值類型變量在賦值和作為參數(shù)傳遞時都會產(chǎn)生一次復制動作,即對原值的拷貝

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ù)組大小
?? ?// 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ù)組大小已設定為2
?? ?
?? ?// 4.聲明時不設定大小,賦值時指定索引
?? ?// 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的同學,可以參考vector和List,切片就是類似這兩個數(shù)據(jù)結構,直接上代碼:

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ù)),右邊為結束位(不包含結束位數(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關鍵字直接創(chuàng)建切片,

語法:make([]類型, 大小,預留空間大小),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的切片,并預留10個元素的存儲空間(預留空間不知道有什么用?)
?? ?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值可以是任何可以用==判斷的值類型,對應的值類型沒有要求。

直接上代碼,如下:

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 對應的值
? ? 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 也是類型相關的,一個 channel 只能傳遞一種類型的值。

聲明:var 通道名 chan 通道傳遞值類型 或 make 函數(shù)初始化:make(chan 值類型, 初始存儲空間大小)

說白了,通道類似消息隊列,主要應用在并發(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í)行權限給子 Go 程,即通過 go 開啟的 goroutine,不然主程序會直接結束
? ? 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)
? ? }
}

運行結果如下:

// ------  輸出:--------
1
a
寫入: 1
寫入: 2
寫入: 3
讀?。?1
讀取: 2
讀?。?3
寫入: 4
寫入: 5
寫入: 6
讀?。?4
讀?。?5
讀?。?6
寫入: 7
寫入: 8
寫入: 9
讀?。?7
讀?。?8
讀?。?9

goroutine channel 的詳細用法會有相應的博客專門來講這一章節(jié),具體可在我的個人主頁里面,找一下相關的博客參考。

八、結構體(struct)

結構體是一種聚合的數(shù)據(jù)類型,是由零個或多個任意類型的值聚合成的實體。每個值稱為結構體的成員,和java中的class是一個意思:

package main

import "fmt"

// 定義一個結構體 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 關鍵字,格式為:

// 定義一個接口
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 結構體
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ù)字轉字符串
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
}

到此這篇關于Go語言數(shù)據(jù)類型詳細介紹的文章就介紹到這了,更多相關Go數(shù)據(jù)類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Go routine調(diào)度詳解

    Go routine調(diào)度詳解

    這篇文章主要介紹了Go routine調(diào)度詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • 用Go寫一個輕量級的ssh批量操作工具的方法

    用Go寫一個輕量級的ssh批量操作工具的方法

    這篇文章主要介紹了用Go寫一個輕量級的ssh批量操作工具的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • Go map底層實現(xiàn)與擴容規(guī)則和特性分類詳細講解

    Go map底層實現(xiàn)與擴容規(guī)則和特性分類詳細講解

    這篇文章主要介紹了Go map底層實現(xiàn)與擴容規(guī)則和特性,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2023-03-03
  • 深入理解go unsafe用法及注意事項

    深入理解go unsafe用法及注意事項

    go雖然是一種高級語言,但是也還是給開發(fā)者提供了指針的類型unsafe.Pointer,我們可以通過它來直接讀寫變量的內(nèi)存,本文來了解一下?unsafe?里所能提供的關于指針的一些功能,以及使用unsafe.Pointer的一些注意事項
    2024-01-01
  • 使用go讀取gzip格式的壓縮包的操作

    使用go讀取gzip格式的壓縮包的操作

    這篇文章主要介紹了使用go讀取gzip格式的壓縮包的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go語言中內(nèi)存管理逃逸分析詳解

    Go語言中內(nèi)存管理逃逸分析詳解

    所謂的逃逸分析(Escape?analysis)是指由編譯器決定內(nèi)存分配的位置嗎不需要程序員指定。本文就來和大家簡單分析一下Go語言中內(nèi)存管理逃逸吧
    2023-03-03
  • 一文帶你了解Go語言中time包的時間常用操作

    一文帶你了解Go語言中time包的時間常用操作

    在日常開發(fā)中,我們避免不了時間的使用,我們可能需要獲取當前時間,然后格式化保存,也可能需要在時間類型與字符串類型之間相互轉換等。本文將會對?Go?time?包里面的常用函數(shù)和方法進行介紹,需要的可以參考一下
    2022-12-12
  • Go語言生成隨機數(shù)的方法

    Go語言生成隨機數(shù)的方法

    這篇文章主要介紹了Go語言生成隨機數(shù)的方法,實例分析了Go語言生成隨機數(shù)的原理與實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 一文詳解golang中的gmp模型

    一文詳解golang中的gmp模型

    這篇文章主要介紹了golang中的gmp模型的誕生、概念及調(diào)度講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Go編程中常見錯誤和不良實踐解析

    Go編程中常見錯誤和不良實踐解析

    這篇文章主要為大家介紹了Go編程中常見錯誤和不良實踐解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01

最新評論