中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

go語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)

這章主要描述如何定義變量、常量、go內(nèi)置類型及go程序設(shè)計(jì)中的一些技巧

網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、小程序開(kāi)發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了奉節(jié)免費(fèi)建站歡迎大家使用!

定義變量

go中定義變量的方式很多:

  1. 使用var關(guān)鍵字是最基本的定義變量的方式,與C語(yǔ)言有些不同,如下:
    var variable_name type
  2. 定義多個(gè)變量
    var name1,name2,name3 type
  3. 定義變量同時(shí)初始化
    var name1 string = "liming"
  4. 同時(shí)初始化多個(gè)變量
    var name1,name2,name3 string = "a", "c", "d"
  5. 直接忽略類型同時(shí)初始化
    var name1,name2,name3 = "a", "c", "d"
  6. 最簡(jiǎn)化的,只適用于函數(shù)內(nèi)部使用,全局變量中無(wú)法使用,否則報(bào)錯(cuò)
    name1,name2,name3 := "a", "c", "d"

    常量

    常量就是確定的值,無(wú)法改變。(可以是布爾值、可以是字符串、數(shù)值等類型)
    語(yǔ)法如下:
    const name type = value

    內(nèi)置基礎(chǔ)類型(重點(diǎn)關(guān)注rune、byte、string類型)

    go語(yǔ)言中三種內(nèi)置文本類型:string、(字節(jié))byte、(符文)rune

  7. Boolean類型
    它的值只有ture和false,默認(rèn)是false。定義如下:
    var a bool
  8. 數(shù)值類型
    帶符號(hào)和不帶符號(hào)兩種。同時(shí)支持int和uint。這兩種類型的長(zhǎng)度一樣。但具體長(zhǎng)度由編譯器決定。
    go里面也有直接定義好位數(shù)的類型:rune,int8,int16,int32,int64和byte,uint8,uint16,uint32,uint64。
    其中rune是int32的別名,byte是uint8的別名。具體可見(jiàn)官網(wǎng)。
    需要注意的是:不同類型的變量之間不允許互相賦值和操作,不然編譯時(shí)會(huì)報(bào)錯(cuò)。
    浮點(diǎn)數(shù)的類型有float32和float64兩種,默認(rèn)是后者。
    復(fù)數(shù):默認(rèn)類型是complex128(64位實(shí)數(shù)+64位虛數(shù))。還有complex64。
    var c complex64 = 6+5i //6是實(shí)數(shù)部分,5是虛數(shù)部分,i是虛數(shù)的單位。
    fmt.Printf("value is :%v",c)
  9. 字符串
    go中字符串采用的都是utf-8字符集編碼。雙引號(hào)或反引號(hào)括起來(lái)進(jìn)行賦值。反引號(hào)所見(jiàn)即所得,雙引號(hào)可以使用轉(zhuǎn)義字符。
    var a string = "you"
    在go語(yǔ)言中字符串中的字符是不可變的,否則編譯時(shí)會(huì)報(bào)錯(cuò):cannot assign to s[0]
    var s string = "hello"
    s[0] = 'c'
    但是實(shí)際中會(huì)應(yīng)用到更改字符串,可以采用變通的手法rune或byte。因?yàn)閟tring類型在go中是以byte數(shù)組存儲(chǔ)的,它不是以字符存儲(chǔ)的。
    s:="hello"
    c:=[]rune(s) //這里也可以轉(zhuǎn)成byte型數(shù)組。
    c[0]='c'
    s1:=string(c)
    fmt.Println(s1)
    也可以通過(guò)切片的方式來(lái)實(shí)現(xiàn)更改字符串中的某一個(gè)字符
    s := "hello"
    s = "c" + s[1:]
    fmt.Println(s, s[2])
    操作字符串:
    s1,s2,s3:="I","am","studying"
    s4:=s1+s2+s3
    fmt.Println(s4)
  10. 錯(cuò)誤類型
    error類型是go的內(nèi)置類型。專門用來(lái)處理錯(cuò)誤信息。go的package里面還有專門的包errors來(lái)處理錯(cuò)誤:
    err := errors.New("emit macho dwarf: elf header corrupted")
    if err != nil {
    fmt.Print(err)
    }

    go數(shù)據(jù)底層的存儲(chǔ)

  11. 基礎(chǔ)類型底層都是分配了一塊內(nèi)存,然后在分配的內(nèi)存中存儲(chǔ)了相應(yīng)的值:
    go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
    Even though i and j have the same memory layout, they have different types: the assignment i = j is a type error and must be written with an explicit conversion: i = int(j)
    通過(guò)上圖,我們可以得知I,j,f同處在一個(gè)內(nèi)存布局中。這句話有點(diǎn)不明白。float32盡管和int32有相同的內(nèi)存占有量,但是處在不同的內(nèi)存布局中。
      1. struct類型
        type Point struct{x,y int} //定義了一個(gè)結(jié)構(gòu)體,下圖是給變量p和pp賦值。
        go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
        對(duì)于結(jié)構(gòu)體類型,它是一種用戶可以自定義的類型,它實(shí)際就是用其他類型組合成新的類型
        定義方式:
        type variable_type_name struct{
        member1 type
        member2 type
        member3 type

        }
        聲明變量的類型,如下,variable_name就是一個(gè) variable_type_name類型,同時(shí)賦值
        variable_name := variable_type_name {value1,value2,value3,…}
        當(dāng)然也可以采用以下的方式對(duì)成員進(jìn)行賦值。
        variable_type_name.number1=value1
        在結(jié)構(gòu)體中,成員占有的內(nèi)存也是一個(gè)接一個(gè)連續(xù)的。如上圖中pp和p的內(nèi)存不在同一連續(xù)內(nèi)存地址中,一個(gè)指向的是10和20的地址,一個(gè)是表示的10和20
        也可以通過(guò)下圖進(jìn)行理解
        go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
      1. 字符串類型
        go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
        通過(guò)上面的圖我們可以看到,字符串在內(nèi)存中表現(xiàn)為占用2-word,包含一個(gè)指向字符數(shù)據(jù)的指針和一個(gè)字符串長(zhǎng)度。
        go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
        從上面的結(jié)果我們可以看到,根本無(wú)法改變底層數(shù)組的某元素,這是很安全的。
        Because the string is immutable, it is safe for multiple strings to share the same storage, so slicing s results in a new 2-word structure with a potentially different pointer and length that still refers to the same byte sequence。
        由于其底層不可變性,如果使用slice,則會(huì)造成不必要的浪費(fèi)(因?yàn)橹灰杏玫絪lice,就會(huì)保留該底層數(shù)組)。一般情況在大多數(shù)語(yǔ)言中都避免在字符串中使用slice。
    • 4.slice
      go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
      slice實(shí)際的底層也是數(shù)組,它通過(guò)[]或make定義切片。在內(nèi)存中它是一個(gè)3-word的結(jié)構(gòu),它由ptr(a pointer to the first element of the array)、lenth和capacity組成。len是切片中索引的上線想x[i],而cap是切片容量的上線x[i;j],copy是用于復(fù)制,copy(s1,s2)
      slice string or array 不是一個(gè)copy,它僅僅創(chuàng)建了一個(gè)新的結(jié)構(gòu),這個(gè)結(jié)構(gòu)包含ptr、len、cap
      ,它的底層是沒(méi)有變化,如上圖。
      Because slices are multiword structures, not pointers, the slicing operation does not need to allocate memory, not even for the slice header, which can usually be kept on the stack. This representation makes slices about as cheap to use as passing around explicit pointer and length pairs in C. Go originally represented a slice as a pointer to the structure shown above, but doing so meant that every slice operation allocated a new memory object. Even with a fast allocator, that creates a lot of unnecessary work for the garbage collector, and we found that, as was the case with strings above, programs avoided slicing operations in favor of passing explicit indices. Removing the indirection and the allocation made slices cheap enough to avoid passing explicit indices in most cases
    • 5.map類型
      它的結(jié)構(gòu)體就是一張hashtable,關(guān)于具體的解釋可以參考源碼:
      $GOROOT/src/runtime/hashmap.go
      只截取一部分,自己可以詳細(xì)的看。
      //A map is just a hash table. The data is arranged
      // into an array of buckets. Each bucket contains up to
      // 8 key/value pairs.
      官方給予的說(shuō)明:
      A map is an unordered group of elements of one type, called the element type, indexed by a set of unique keys of another type, called the key type. The value of an uninitialized map is nil
      map類型是一個(gè)引用的類型,它修改鍵值可能會(huì)修改底層的hashtale,類似于slice(reference type)。如下:
      go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
      The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice. If the key type is an interface type, these comparison operators must be defined for the dynamic key values; failure will cause a run-time panic.
      這里參考文檔:
      http://blog.csdn.net/slvher/article/details/44340531
      Go source code - src/pkg/runtime/hashmap.c
      https://golang.org/ref/spec#Map_types

map類型類似于python中字典。實(shí)際就是鍵值對(duì)的集合。語(yǔ)法格式如下:
聲明變量,默認(rèn)map是nil,nil map不能直接賦值,默認(rèn)是0
var map_variable_name map[key_data_type]value_data_type
使用make函數(shù)創(chuàng)建一個(gè)非nil的map,因?yàn)閚il map不能存放鍵值對(duì)。
map_variable_name = make(map[key_data_type]value_data_type,cap)
簡(jiǎn)潔的:map_variable_name := map[key_data_type]value_data_type{k1:v1,k2:v2,….}
以下是兩種定義例子
go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
上面的cap可以省略,但是在用時(shí)最好合理設(shè)置,為什么?
如果里面的key-value鍵值對(duì)超出容量,則容量會(huì)自動(dòng)擴(kuò)容(因?yàn)槊恳淮蔚臄U(kuò)容都是重新分配內(nèi)存和拷貝)
map中的key是獨(dú)一無(wú)二的。
使用len()可以獲得元素個(gè)數(shù)
使用delete()可以操作鍵值對(duì)的刪除
delete(key,value) //注意不能是nil map,否則會(huì)拋出異常panic。
使用for….range對(duì)map進(jìn)行迭代操作。
map的讀取和設(shè)置類似于slice,通過(guò)key來(lái)進(jìn)行操作,但是又有所不同,map中key可以是int、string、float(最好不用float)(只要是支持==或者!=類型的都可以,這里函數(shù)、map、slice不支持),而slice中的索引只能是int類型。value可以是其他任意類型。
map查找比線性搜索快,但是比使用索引訪問(wèn)數(shù)據(jù)的類型慢很多(據(jù)說(shuō)慢100倍)。
注意:
1)map中的元素不是變量,因此不能尋址。具體原因是:map可能會(huì)隨著元素的增多重新分配更大的內(nèi)存空間,舊值都會(huì)拷貝到新的內(nèi)存空間,因此之前的地址就會(huì)失效。
2)map中使用for…range遍歷,(也就是說(shuō)不能使用索引的方式獲取鍵值,但是可以重新賦值)同時(shí)它的迭代順序是不確定的,也就是說(shuō)每執(zhí)行一次結(jié)果的順序都可能不同。在go語(yǔ)言中是有意的這么設(shè)計(jì),是為例避免程序依賴于某種哈希實(shí)現(xiàn),目的是為了程序的健壯。如果非要按順序遍歷,必須顯示對(duì)key排序,可以使用sort包中的String函數(shù)。代碼如下,一般最好不要這樣使用。
import “sort”
var names []string
for ,name := range ages {
names = append(names, name)
}
sort.Strings(names)
for
, name := range names {
fmt.Printf("%s\t%d\n", name, ages[name])
}
map中如果沒(méi)有該key則返回值為0,但是如果該key存在且鍵值是0,如何判斷?
map功能的查找:
value, ok := map[“1”]
if ok{
//處理查到的value值
}
go 語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)

  • 6.零值
    零值,并非是空值,而是變量未賦值時(shí)默認(rèn)的值,通常為0
    int int8 int32 int64 0
    uint 0x0
    rune 0 //實(shí)際就是int32
    byte 0x0 //實(shí)際就是uint8
    float32 float64 0
    bool false
    string “ ”
    參考文檔:
    https://research.swtch.com/godata
    https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/02.2.md
    http://blog.csdn.net/slvher/article/details/44340531
    Go source code - src/pkg/runtime/hashmap.c
    https://golang.org/ref/spec#Map_types

當(dāng)前名稱:go語(yǔ)言中的類型及數(shù)據(jù)結(jié)構(gòu)
網(wǎng)頁(yè)鏈接:http://www.rwnh.cn/article10/jdcgdo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、網(wǎng)站內(nèi)鏈、Google、搜索引擎優(yōu)化標(biāo)簽優(yōu)化、微信公眾號(hào)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)
黑河市| 洛阳市| 安溪县| 连山| 墨玉县| 铜梁县| 莲花县| 曲松县| 容城县| 海阳市| 司法| 温宿县| 弥勒县| 伊宁市| 上杭县| 尼勒克县| 安塞县| 乡宁县| 万州区| 邢台县| 太原市| 沁阳市| 成都市| 定远县| 凉城县| 白银市| 阳东县| 汤原县| 德钦县| 垦利县| 云阳县| 九寨沟县| 衡阳市| 福贡县| 肇东市| 泸水县| 福安市| 郁南县| 锡林浩特市| 兴宁市| 温宿县|