Golang基礎(chǔ)數(shù)據(jù)類型

本節(jié)介紹Golang的基本數(shù)據(jù)類型,字符串,整型,浮點(diǎn)型,數(shù)組,切片

類型 長(zhǎng)度(字節(jié) byte) 默認(rèn)值 說明
bool 1 false
byte 1 0 uint8
rune 4 0 Unicode Code Point, int32
int, uint 8 0 32 或 64 位
int8, uint8 1 0 -128 ~ 127, 0 ~ 255,byte是uint8 的別名
int8, uint8 1 0 -128 ~ 127, 0 ~ 255,byte是uint8 的別名
int16, uint16 2 0 -32768 ~ 32767, 0 ~ 65535
int32, uint32 4 0 -21億~ 21億, 0 ~ 42億,rune是int32 的別名
int64, uint64 8 0
float32 4 0.0
float64 8 0.0
complex64 8
complex128 16
uintptr 4或8 以存儲(chǔ)指針的 uint32 或 uint64 整數(shù)
array 值類型
struct 值類型
string "" UTF-8 字符串
slice nil 引用類型
map nil 引用類型
channel nil 引用類型
interface nil 接口
function nil 函數(shù)

注意項(xiàng):

  • float32大約可以提供小數(shù)點(diǎn)后6位的精度,作為對(duì)比,float64可以提供小數(shù)點(diǎn)后15位的精度。通常情況應(yīng)該優(yōu)先選擇float64,因此float32的精確度較低,在累積計(jì)算時(shí)誤差擴(kuò)散很快,而且float32能精確表達(dá)的最小正整數(shù)并不大,因?yàn)楦↑c(diǎn)數(shù)和整數(shù)的底層解釋方式完全不同 https://studygolang.com/articles/6429

一,字符串

1,字符串長(zhǎng)度與拼接
    var name = "小明!"
    say := "Hello,This is my City"

    fmt.Println(len(name)) // 9 一個(gè)漢字 占3個(gè)字節(jié)
    fmt.Println(len(say)) // 21 英文字母和空格,都占一個(gè)字節(jié)

    fmt.Println(name + " " + say) // + 號(hào)可用于字符串拼接  // 小明! Hello,This is my City
    fmt.Printf("%v %v \n",name,say) // 小明! Hello,This is my City
2,字符串分割
    arr := strings.Split(say," ")  //返回一個(gè)切片:[]string
    fmt.Println(arr) // [Hello,This is my City]
    fmt.Println(len(arr)) // 4
    fmt.Println(cap(arr)) // 4
3,判斷是否包含
    exist := strings.Contains(name,"小")
    fmt.Println(exist) // true
4,判斷子串出現(xiàn)位置,如果沒有出現(xiàn),返回 -1
    idx := strings.Index(say,"i") //第一個(gè)出現(xiàn)的位置
    fmt.Println(idx) // 8 ,是從 0 開始的
    fmt.Println(strings.LastIndex(say,"i")) // 18
5,切片合并成字符串
    fruits := []string{"蘋果","橘子","香蕉"}
    fmt.Println(strings.Join(fruits,",")) // 蘋果,橘子,香蕉
    fmt.Println(reflect.TypeOf(strings.Join(fruits,","))) // string
6,字符串轉(zhuǎn)整形(有兩個(gè)返回值,處理err)
    var strNum1 = "123"
    var strNum2 = "123.456"

    num1,err := strconv.Atoi(strNum1)
    if err != nil {
        num1 = 0
    }
    fmt.Println(num1) // 123

    num2,err2 := strconv.Atoi(strNum2)
    if err2 != nil {
        fmt.Println(err2)  //strconv.Atoi: parsing "123.456": invalid syntax
        num2 = 0 //被觸發(fā),同理,strNum2 = "123.0"也會(huì)被觸發(fā)
    }
    fmt.Println(num2) // 0
7,字符串轉(zhuǎn)浮點(diǎn)型:
    num3,err3 := strconv.ParseFloat(strNum1,32)
    if err3 != nil {
        num3 = 0
    }
    fmt.Println(num3) // 123

    num4,err4 := strconv.ParseFloat(strNum2,64)
    if err4 != nil {
        num4 = 0
    }
    fmt.Println(num4) //123.456

二,整形與浮點(diǎn)型

1,數(shù)字類型之間互相轉(zhuǎn)換:
    var num6 int64 = 100
    var num7 float64 = 123.356
    fmt.Println(reflect.TypeOf( int32(num6) )) // int32
    fmt.Println(reflect.TypeOf( float64(num6) )) //float64

同理,還有int8() , int16() , int64() , float32() 等函數(shù)

2,整形轉(zhuǎn)字符串:
    str1 := strconv.Itoa( int(num6) ) //這個(gè)函數(shù)只能傳入int類型的,不能傳入int64等其他整型的,淦
    fmt.Println(str1) // 100
3,浮點(diǎn)型轉(zhuǎn)字符串:
    str2 := strconv.FormatFloat(num7,'f',2,64)
    fmt.Println(str2) // 123.36

三,數(shù)組

func main()  {
    // 1,聲明:元素類型 元素個(gè)數(shù)
    var strList [5]string
    fmt.Println(strList) //[    ] 聲明一個(gè)數(shù)組后會(huì)自動(dòng)設(shè)置其默認(rèn)值

    var numList [5]int
    fmt.Println(numList) //[0 0 0 0 0]

    //2,聲明,并初始化
    var list3 =  [5]int{1,2,3}
    fmt.Println(list3) //[1 2 3 0 0]

    //3,聲明,初始化,自動(dòng)識(shí)別數(shù)組個(gè)數(shù):
    var list4 = [...]int{1,2,3,4}
    fmt.Println(list4) //[1 2 3 4]
    fmt.Println(cap(list4)) //[1 2 3 4]
    fmt.Println(len(list4)) //[1 2 3 4]

    //4,函數(shù)傳參與遍歷
    getList(list3)

}

func getList(list [5]int){
    //第一種遍歷:
    for i := 0; i < len(list); i++ {
        fmt.Println(list[i]);  // 1 2 3 0 0  //通過下標(biāo)訪問元素
    }

    //第二種遍歷:
    for key, value := range list {
        fmt.Printf("%v => %v \n",key,value)  // 0 => 1
    }

}

注意事項(xiàng):

  • 1,數(shù)組:是同一種數(shù)據(jù)類型的固定長(zhǎng)度的序列。
  • 2,長(zhǎng)度是數(shù)組類型的一部分,因此,var a[5] int和var a[10]int是不同的類型。fmt.Println(reflect.TypeOf(list3)) //[5]int
  • 3,訪問越界,如果下標(biāo)在數(shù)組合法范圍之外,則觸發(fā)訪問越界,會(huì)panic
  • 6,數(shù)組是值類型,賦值和傳參會(huì)復(fù)制整個(gè)數(shù)組,而不是指針。因此改變副本的值,不會(huì)改變本身的值。
  • 7,支持 "=="、"!=" 操作符,因?yàn)閮?nèi)存總是被初始化過的。
  • 8,指針數(shù)組 [n]*T,數(shù)組指針 *[n]T。
    var list5 = [3]int{1,2,3}
    var list6 = [3]int{1,2,3}
    fmt.Println( list5 == list6 ) //true

    var list7 = [3]int{1,2,4}
    fmt.Println( list6 == list7 ) //false

1,多維數(shù)組:

    var list8 = [2][3]int{
        {1,2,3},
        {7,8,9},
    }
    fmt.Println(list8) // [[1 2 3] [7 8 9]]

四,切片

需要說明,slice 并不是數(shù)組或數(shù)組指針。它通過內(nèi)部指針和相關(guān)屬性引用數(shù)組片段,以實(shí)現(xiàn)變長(zhǎng)方案。

  1. 切片:切片是數(shù)組的一個(gè)引用,因此切片是引用類型。但自身是結(jié)構(gòu)體,值拷貝傳遞。
  2. 切片的長(zhǎng)度可以改變,因此,切片是一個(gè)可變的數(shù)組。
  3. 切片遍歷方式和數(shù)組一樣,可以用len()求長(zhǎng)度。表示可用元素?cái)?shù)量,讀寫操作不能超過該限制。
  4. cap可以求出slice最大擴(kuò)張容量,不能超出數(shù)組限制。0 <= len(slice) <= len(array),其中array是slice引用的數(shù)組。
  5. 切片的定義:var 變量名 []類型,比如 var str []string var arr []int。
  6. 空切片等于nil :fmt.Println(slice1 == nil) //true。 如果 slice == nil,那么 len、cap 結(jié)果都等于 0。
1,切片的各種定義:
    //切片的聲明:1,聲明一個(gè)不定長(zhǎng)數(shù)組,
    var slice1 []int
    fmt.Println(slice1) // []
    fmt.Println(slice1 == nil) //true

    slice1 = append(slice1,1) //增加一個(gè)元素
    fmt.Println(slice1) // [1]

    //切片的聲明:2,通過make函數(shù)創(chuàng)建
    var slice2 []int = make([]int,2)// []數(shù)據(jù)類型 ,長(zhǎng)度
    fmt.Println(slice2)

    //slice1[2] = 4 //注意:不可以直接為不存在的鍵賦值,需要通過append增加后才能 set,get
    slice2 = append(slice2,4)
    fmt.Println(slice2[2]) //4

    //通過截取數(shù)組,來生成切片:slice = num[startIndex:endIndex] 如果不填則為默認(rèn)值:num[0 : max]
    var num =  [5]int{1,3,5,7,9}
    var slice3 = num[:]
    fmt.Println(slice3) //[1 3 5 7 9]

    slice3 = num[1:]
    fmt.Println(slice3) //[3 5 7 9] //可以看到,包含startIndex

    slice3 = num[:2]
    fmt.Println(slice3) //[1 3] //可以看到,不包含endIndex
2,切片的長(zhǎng)度
  • len()函數(shù)可以獲取切片當(dāng)前長(zhǎng)度,cap()函數(shù)可以獲取切片的最大長(zhǎng)度
    var x []int = make([]int,3,5)
    fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) //len=3 cap=5 slice=[0 0 0]
    x = append(x,1)
    x = append(x,2)
    x = append(x,3)
    x = append(x,4)
    x = append(x,5)
    x = append(x,6)
    x = append(x,1) //經(jīng)過試驗(yàn)可以發(fā)現(xiàn),make定下的最大長(zhǎng)度cap = 5,其實(shí)是可以增加到6,7個(gè)元素的,并不是最大只能存5個(gè)
    x = append(x,1) //當(dāng)切片長(zhǎng)度超過cap時(shí),cap會(huì)增長(zhǎng)一倍,就是用自己乘以2,直到放得下所增加的元素

    fmt.Println(x)
    fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) //len=11 cap=20 slice=[0 0 0 1 2 3 4 5 6 1 1]
3,遍歷

切片的遍歷與上面數(shù)組相同
語言范圍Range:

  • 1,語法: key,value := range + 變量 : 該用法返回變量中的 元素的 索引和值,如果是集合,則返回key - value 對(duì)
  • 2,range + 變量,他有兩個(gè)返回值,如果某一個(gè)返回值你不需要用到,用 _ 接收
4,切片的本質(zhì)
func main() {
    slice := []int{1, 2, 3, 4, 5}
    fmt.Printf("切片:%v\n", slice) //切片:[1 2 3 4 5]
    fmt.Printf("slice pointer is : %p \n",slice)  // slice pointer is : 0xc00000a2d0
    fmt.Printf("&slice pointer is : %p \n",&slice)  // &slice pointer is : 0xc0000044a0

    changeSlice1(slice)
    fmt.Printf("切片:%v\n", slice) //切片:[1 2 10 4 5]
    fmt.Printf("slice pointer is : %p \n",slice) // slice pointer is : 0xc00000a2d0
    fmt.Printf("&slice pointer is : %p \n",&slice) // &slice pointer is : 0xc0000044a0
}


func changeSlice1(slice []int) {
    slice[2] = 10
    fmt.Printf("切片:%v\n", slice) //切片:[1 2 10 4 5]
    fmt.Printf("slice pointer is : %p \n",slice) // slice pointer is : 0xc00000a2d0
    fmt.Printf("&slice pointer is : %p \n",&slice) // &slice pointer is : 0xc000004520  指針已經(jīng)不同,可見發(fā)生了拷貝
}
  • 1,由上面的代碼中可以看到,打印傳入函數(shù)的slice(值),一直都是 0xc00000a2d0 ,但是這個(gè)值的指針:&slice,是不一樣了的,證明值經(jīng)過了拷貝。那為什么函數(shù)里面的切片的改變,導(dǎo)致了調(diào)用處的切片也一并改變了呢?因?yàn)榍衅谋举|(zhì)就是一個(gè)由:保存該切片元素的數(shù)組的指針(也就是上面打印出來的0xc00000a2d0 ) + len + cap 的結(jié)構(gòu)體組成,它傳了這個(gè)值(0xc00000a2d0)進(jìn)去,進(jìn)而函數(shù)changeSlice1()對(duì)這個(gè)值所指向的真實(shí)數(shù)組做處理,從而,導(dǎo)致了調(diào)用出的切片的值也發(fā)送了改變。
  • 2,Go的參數(shù)傳遞都是值傳遞,參考資料:https://blog.csdn.net/chen_peng7/article/details/89247047
    image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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