go數據類型識別

go數據類型

go語言數據類型主要分爲如下的四個大類:javascript

  1. 基礎類型(整數,浮點數,負數,布爾值等)
  2. 聚合類型(數組,結構體)
  3. 引用類型(slice,指針,map,函數,通道)
  4. 接口類型

go語言是擁有類型系統的語言,相對於筆者最熟悉的javascript這種動態且無類型的語言來講有着長遠的好處.經過類型系統能在編譯階段減小必定的運行時錯誤.例如在go語言中不一樣類型之間必須經過顯示轉換來進行賦值等操做.本文主要從go語言中的基礎類型開始,逐步的講解go語言中幾種基本的引用類型.前端

基礎類型

字符串

字符串是不可改變的字節序列.能夠經過[i:j]操做符截取對應字符串的子串.因爲字符串不可改變的特色,子串和母串共用一端底層內存.java

s := "hello world"
b := s[6:] // [i:j] 從i開始不包括j   world
複製代碼

常量

常量是一種表達式,能夠在編譯的階段來肯定相應的值.在聲明常量的時候能夠指定類型和值(若是沒有指定類型會經過值來推斷常量的類型).在連續聲明多個常量的時候,主要有如下兩種方式:數組

const (
  a  = iota
  b
  c
  d
)
// a b c d 0 1 2 3
const (
  a = 1
  b
  c = 2
  d
)
// a b c d 1 1 2 2
複製代碼

無類型常量(常量字面量)是尚未肯定從屬類型的常量值.無類型常量相對於一樣的有類型的常量有更大的精度.例如0.0相對有浮點數擁有更大的精度.在將無類型常量複製給對應的變量的時候,賦值的變量會轉換爲無類型常量默認的類型.app

i := 0 // int(0)
b := 0.0 // float64(0.0)
複製代碼

數組

數組是具備固定長度的存儲相同數據類型的序列.因爲數組在聲明的時候對長度有限制,當存儲元素到達數組的容量的時候就須要申請新的內存空間來進行數據的存儲.因此在存儲數據上通常不會使用數組.數組元素的初始值是該類型的零值.在聲明數組的時候須要顯示的指定長度和類型.函數

數組操做

能夠經過下面這兩種方式聲明一個數組.性能

test := [...]int{1,2,3} 
test := [3]int{1,2,3}
a := [2]int{}  // 定義長度爲2的數組
a[0] // 0  經過下標訪問
b := [2]int{}
a == b // true
c := [3]int{}
a == c // false 這行代碼在編譯的時候會報錯,由於長度也屬於數組類型的一部分,長度2和長度3的數組沒法比較

array1 = [3]int{1,2,3}
array2 = [3]int{}
array2 = array1  // 同類型的數組能夠複製,對於指針數組只複製指向.
複製代碼

注意點

go語言在傳遞函數的參數的時候,老是以值的方式進行傳遞,對於長數組能夠考慮經過傳遞指針的方式來下降複製的性能學習

slice

slice是用相同類型元素的可變長度序列.能夠基於一個已有的數組來建立這個數組的slice.slice有三個屬性:指針,容量,長度.能夠在一個數組的基礎上產生多個slice,它們共享內存空間.須要注意的是slice能夠理解爲對原數組的引用,經過對slice的修改是會影響到底層數組的.spa

聲明和使用

聲明切片

主要能夠經過切片字面量和內置的make函數來實現切片的聲明.指針

var test = make(int[], 3, 5) // make(type[], len, cap) 聲明一個長度爲3容量爲5的切片
var test1 = []int{1,2} // 聲明一個長度和容量都爲2的切片
var test2 = []int{ 99: 1 } // 聲明一個長度和容量爲100的切片,初始化第100的元素爲1
//聲明數組與聲明切片的對比 注意聲明slice的時候不須要指定長度
test3 := [2]int{1,2}
test4 := []int{1,2}
複製代碼

操做切片

var num = [10]int{1,2,3,4,5,6,7,8,9,10}
a := num[1:4] // 操做符[i:j]建立一個新的slice,引用原數組i到j-1個元素.slice的容量是slice起始元素到底層數組最後一個元素之間的個數,切片a只能看到底層數組i以及以後的元素
len(a) // 3 獲取切片的長度
cap(a) // 9 獲取切片的容量
a[0] = 100
b := a[:5] // 能夠在一個已有的slice上擴充容量,產生新的slice
len(b) // 4
cap(b) // 9
// 經過切片建立切片
slice := []int{1,2,3,4,5}
newSlice := slice[1:3]
複製代碼

在上面最後的一個例子中,能夠經過切片建立切片,slice能看到底層數組的全部元素,newSlice只能看到底層數組1(包括)以後的元素.

切片增加

能夠經過內置的append函數來動態的增長元素到切片中.

slice := []int{1,2,3,4,5}// 聲明一個切片
newSlice := slice[1:2] // 在已有切片上建立一個切片 切片的長度是1 容量是4
newSlice = append(newSlice, 10) 
fmt.Println(slice[2]) // 10
複製代碼

在剛纔的例子中,因爲newSlice的容量是4,在進行append的時候沒有達到容量的限制,因此底層數組的元素被修改了.對於這種狀況在建立切片刀時候就限制切片的容量和長度一致.這樣當進行元素的添加的時候,append函數會新建立底層數據.

slice := []int{1,2,3,4,5}// 聲明一個切片
newSlice := slice[1:2:2] // 在已有切片上建立一個切片 操做符[i:j:k] 長度 j-i  容量 k-i
newSlice = append(newSlice, 10) 
fmt.Println(slice[2]) // 3
複製代碼

append還支持批量的增長元素.

a := []int{1,2}
  b := []int{3,4}
  c := append(a, b...)
// 迭代切片
  for _, value := range c {
	  fmt.Println(value)
  }
複製代碼

map

在go中map是對散列表的引用.散列表是無序的鍵值的結合.能夠經過以下的方式建立map:

var test = make(map[string]int) // 聲明map的鍵值的類型  map的值也能夠是複合類型 例如  make(map[string]map[string]int)
test["name"] = 100  // 賦值
var person = map[string]int{ "card": 1, id: "2" }  //聲明並初始map
person["card"] // 1
delete(person, "card") // 刪除對應的屬性
if value, ok := test["haha"]; !ok {
  // 不存在對應的鍵值
}
複製代碼

能夠聲明一個nil映射,nil映射不能用於存儲建值.

var a map[string]int
a["hahh"] = 1 // 報錯
複製代碼

map有如下幾點須要特別注意:

  1. 在賦值map類型的值的時候,須要對map進行初始化.初始化的map的值是對應類型的零值.
  2. 獲取鍵值的操做返回值,來判斷對應元素是否存在map中.
  3. map的鍵值是可使用==來比較的(slice不能夠).
  4. map是引用類型,在函數間傳遞的時候會對原值進行修改.

結構體

結構體是將多個命名變量組合到一塊兒的聚合數據類型.能夠經過下面的方式聲明一個結構體:

type Person struct {
    name string
    id,age  int
    baby []int
}
var haha Person
// 下面這幾種對結構體變量賦值的方式是等同的
haha.name = "haha"

test := Person{ name: "100" } // 指定變量的值的方式初始化變量

name := &haha.name
*name = "100"

var copyPerson *Person = &haha
copyPerson.name = "100"
複製代碼

在聲明結構體的時候須要注意如下的幾點:

  1. 結構體變量的大小寫決定變量是否能夠導出(能夠被其餘導出的包讀寫)
  2. 結構體變量不能夠擁有本身自己的結構體類型,能夠經過自身結構體類型的指針來實現遞歸結構
  3. 若是結構體全部的成員變量是可比較的,那麼這個結構體是可比較的

結構體嵌套

在定義結構體的成員的時候,go容許只指定成員的類型來實現成員的聲明.經過這種方式定義的結構體成員成爲匿名成員.匿名成員的類型必須是一種命名類型或者指向命名類型的指針.匿名成員能夠爲方便變量提供便捷的操做.

type Circle struct {
    x int
    y int 
    radius int
}
type Wheel struct {	
  Circle
  color string
}
wheel := Wheel{Circle{ 10, 10, 19}, "red"}
// wheel.x = 10
複製代碼

後記

我本身在寫一個公衆號-前端小板凳,主要分享我學習前端和工做中的一些想法,歡迎你們關注.

相關文章
相關標籤/搜索