今天醒來發現眾志成城獎沒了,在最後一天突然有一團35個人的team參賽
事已至此還是繼續寫文吧,今天來講Go語言的內建資料結構,比較常見的有array, slice, map
// var <valName> [<length>]<type>
// length: array長度
// type: array類型
var byteArray [32]byte
// 宣告多維Array
var multipleDimensionArray [312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312][312]int
// 也能在宣告同時賦值
array := [...]float64{7.0, 8.5, 9.1}
[123]int
跟[456]int
為不同的類別// 使用[...]讓Go編譯器自己算長度
originalArray := [...]int{1, 2, 3, 4, 5}
after := originalArray
// some of modify to original array
after[3] = 7
fmt.Printf("original Array: %#v\n", originalArray) // 1, 2, 3, 4, 5
fmt.Printf("Array after modified: %#v\n", after) // 1, 2, 3, 7, 5
可以注意到就算修改了after中的值,originalArray還是沒有改變。var originalArray [4]int
var after *[4]int
fter = &originalArray
after[3] = 7
fmt.Printf("original Array: %#v\n", originalArray) // 1, 2, 3, 7, 5
fmt.Printf("Array after modified: %#v\n", *after) // 1, 2, 3, 7, 5
在介紹Array時說到可以使用pointer來提昇效能,不過Go官方比較建議使用slice進行操作。在實際開發中也比較少使用Array
Slice本質上算是一個對於它自己底層的Array的window,所以在function中修改slice參數的值時也會同時影響到原本底層的array
slice 只存了能夠連結到底層 array 的 pointer,在思考的時候,要把 "slice" 當成一個遮罩或視窗(window),透過它過濾原本 array 的內容後,看到的內容才是 slice 的結果。
順帶一提你其實可以把slice當成一個struct,並且slice初始化後如果沒有賦值的話預設值為nil
type slice struct {
array unsafe.Pointer //指向底層array的pointer
len int //長度(目前slice中元素數量)
cap int //容量(目前slice中做多能存多少)
}
//
lengthOfSlice := len(slice_)
sliceOfSlice := cap(slice_)
var slices []int
pi := []int{3,1,4,1,5,9,2,6} // 中括號內不放任何物件才是slice
// 從現有array 或slice建立slice
newSlice = oldSlice
newSlice = arr[:] // 以arr作為底層`array`
newSlice = arr[4:7] // 以arr作為底層`array`,並選取其中的index (4~7)進行遮罩
anotherNewSlice = newSlice // 兩個變數都是指向同一個記憶體位置
// 也可以透過make([]T, length, capacity)來建立(如果你已經確定slice大小)
madeSlice := make([]int, 0, 5)
補充一下,不管是slice還是array,在獲取元素([k]
)時index千萬不可為負數或超出底層array的capacity
func append(s []T, vs ...T) []T
newSlice = append(oldSlice, newElement1, newElement2) // append兩個新元素
newSlice = append(oldSlice, appendSlice...) // append整個slice(等同python的list.extend())
func copy(dst, src []T) int
size = high-low
cloneSlice = make([]T, size)
copy(cloneSlice, oldSlice[low: high])
cloneSlice
的元素數量如果「多於」被複製進去的元素時,會用 zero value 去補。例如,當cloneSlice
的長度是 4,但只複製 3 個元素進去時,最後位置多出來的元素會補預設值。cloneSlice
的元素數量如果「少於」被複製進去的元素時,超過的元素不會被複製進去。例如,當 cloneSlice 的長度是 1,但卻複製了 3 個元素進去時,只會有 1 個元素被複製進去。
newSlice = oldSlice[start: end]
須要留意的是,在 golang 中使用 : 來切割 slice 時,並不會複製原本的 slice 中的資料,而是建立一個新的 slice,但實際上還是指稱到相同位址的底層 array(並沒有複製新的),因此還是會改到原本的元素:
func main() {
scores := []int{1, 2, 3, 4, 5}
newSlice := scores[2:4]
fmt.Println(newSlice) // 3, 4
newSlice[0] = 999 // 把原本 scores 中 index 值為 3 的元素改成 999
fmt.Println(scores) // 1, 2, 999, 4, 5
}
func main() {
s := []int{1, 2, 3, 4, 5}
newSlice := s[1:3] // [2,3], len = 5, cap = 5
// 沒有指定 end index 並不會 expand slice
nonExpandedSlice := newSlice[0:] // [2, 3]
// 如果想要 expanded slice 需要指定 end index 才行
expandedSlice := newSlice[0:4] // [2, 3, 4, 5]
}
基本上等同於python的dict
或是C++的std::unordered_map
,不過定義完後需要透過make
來初始化才能使用。
var m map[string]func() int // 對,你可以把function作為value
func a() int {
return 1
}
func main() {
m = make(map[string]func() int)
// 設定指定key的值
m["a"] = a
// 或是使用賦值宣告
var m = map[string]func() int{
"a": a,
}
// 或是直接簡單宣告
m := map[string]func() int{
"a": a,
}
}
至於要獲取map中指定的值的話除了一般的val = map[key]
以外也能透過val, ok = map[key]
來初步檢查該key是否在map中,至於刪除元素則是透過delete(map, key)
來刪除元素
那麼今天的文章就到這告一段落,如果我的文章有任何地方有錯誤請在留言區反應
明天將會介紹Go語言的函式與log