周天辣 昨天全員核酸沒有陽性 如果再有兩天陰性的話 就有機(jī)會樓棟能解封啦 最好的情況希望能出現(xiàn) 周二能回去!
在寢室里閑著也是閑著 還是學(xué)一下go吧 把剩下的基礎(chǔ)的給學(xué)完
希望好運(yùn)伴隨!
希望未來順利
go語言中仍舊保持了有指針的特性 這個還是非常欣慰的
準(zhǔn)確來說應(yīng)該和c/c++差別并不大 唯一的差別是不能進(jìn)行指針運(yùn)算
下面是例子111.go
package main
import "fmt"
func main() {i, j := 1, 2
p := &i
fmt.Println(*p, i, j)
p = &j
fmt.Println(*p, i, j)
*p = 3
fmt.Println(*p, i, j)
}
運(yùn)行效果
命名方式相比于c語言有所不一樣 其他的基本大致相同type name struct
然后從這里我自己去搜了10分鐘的資料
發(fā)現(xiàn)go語言的內(nèi)存分配和c++ 完全不一樣
第一點(diǎn) c++需要自己手動解決內(nèi)存分配問題 而go語言是自動回收
第二點(diǎn) go語言會自動分析該對象是否是需要分配內(nèi)存 決定于內(nèi)存逃逸行為 go語言的內(nèi)存分析我剛剛又花了20分鐘看了一下 發(fā)現(xiàn)不像是c++那樣 什么對象是動態(tài)分配的 什么是靜態(tài)分配(在棧中)定義的時候 自己都清楚 而是取決于當(dāng)前對象是否能被外部引用 go語言還是偏向于分配棧對象的 但是對于沒有辦法確認(rèn)是否會被外部引用時 只能放于堆中 用GC來管理
關(guān)于內(nèi)存分配問題 這個后面還要花很多事情去研究研究 下面寫了很多 來看究竟結(jié)構(gòu)體的內(nèi)存分配情況 以及結(jié)構(gòu)體的初始化
111.go
package main
import "fmt"
type Node struct {val int
next *Node
}
var global_ptr *Node
func PtrGo() {global_ptr = &Node{}
global_ptr.val = -1
}
func main() {// 初始化1
var dummynode1 Node
dummynode1.val = -1 //初始化為0后 再賦值
ptr1 := &dummynode1
fmt.Printf("%d %p %s%p %s%p %s\n", dummynode1.val, dummynode1.next, "ptr addr:", &ptr1, "struct addr:", ptr1 , "way 3")
//初始化2
dummynode2 := Node{-1, nil}
ptr2 := &dummynode2
fmt.Printf("%d %p %s%p %s%p %s\n", dummynode2.val, dummynode2.next, "ptr addr:", &ptr2, "struct addr:", ptr2, "way 3")
//初始化3
dummynode3 := new(Node)
dummynode3.val = -1
ptr3 := dummynode3
fmt.Printf("%d %p %s%p %s%p %s\n", dummynode3.val, dummynode3.next, "ptr addr:", &ptr3, "struct addr:", ptr3, "way 3")
//初始化4
PtrGo()
fmt.Printf("%d %p %s%p %s%p %s\n", global_ptr.val, global_ptr.next, "ptr addr:", &global_ptr, "struct addr:", global_ptr, "way 4")
}
運(yùn)行效果
結(jié)構(gòu)體不管是指針還是直接對象訪問結(jié)構(gòu)體內(nèi)部值 都是通過.
符號來訪問 不用指針->
來訪問了
第二個 初始化規(guī)則 上面的方式已經(jīng)寫完了初始化的方式
111.go
package main
import "fmt"
type Node struct {val int
next *Node
}
func main() {var dummynode1 = Node{-1, nil}
fmt.Println(dummynode1)
var dummynode2 = Node{val : -1}
fmt.Println(dummynode2)
var dummynode3 = Node{next : nil}
dummynode3.val = -1
fmt.Println(dummynode3)
dummynode4 := Node{-1, nil}
fmt.Println(dummynode4)
dummynode5 := new(Node)
dummynode5.val = -1
fmt.Println(*dummynode5)
}
運(yùn)行效果
構(gòu)造方式和c語言類似 聲明方式仍舊是golang化
簡單的例子應(yīng)用
package main
import "fmt"
func main() {var strs [2]string
strs[0] = "Hello,"
strs[1] = "World!"
fmt.Println(strs[0], strs[1])
}
運(yùn)行效果
數(shù)組的初始化辦法
下面有這幾種
111.go
package main
import (
"fmt"
)
func main() {var nums1 [10]int = [10]int {1, 2, 3}
for i := 0; i< 10; i++ {fmt.Printf("%d ", nums1[i])
}
fmt.Println()
var nums2 = [10]int{1, 2, 3}
for _, num := range nums2 {fmt.Printf("%d ", num)
}
fmt.Println()
nums3 := [...]int{1, 2, 3}
for _, num := range nums3 {fmt.Printf("%d ", num)
}
fmt.Println()
nums4 := [10]int{0:1, 1:2, 2:3}
for _, num := range nums4 {fmt.Printf("%d ", num)
}
fmt.Println()
var nums5 [10]int
nums5[0] = 1
nums5[1] = 2
nums5[2] = 3
for _, num := range nums5 {fmt.Printf("%d ", num)
}
fmt.Println()
}
運(yùn)行效果
切片在還沒有學(xué)習(xí)Go語言的時候就聽說了其鼎鼎大名
所以我們還是來接觸一下
slice的底層實現(xiàn) 本質(zhì)還是根據(jù)的數(shù)組的底層 可以說用指針來表示數(shù)組的開始位置
三個數(shù)據(jù)結(jié)構(gòu)支持slice指針 size capacity
我認(rèn)為如果是從數(shù)組切分出來的切片 不擴(kuò)容 此時開銷是最小的
但是如果要append元素 此時可以將其看作是c++ vector
本質(zhì)上擴(kuò)容的機(jī)制還是另外申請容量
切片初始化的方法很多 為了后面使用起來更得心應(yīng)手 還是挨個挨個列出來吧
111.go
package main
import (
"fmt"
)
func main() {//初始化1 剛開始為空切片nil
slice1 := []int{}
fmt.Println("before append, length:", len(slice1), ", capacity:", cap(slice1))
for i := 0; i< 10; i++ {slice1 = append(slice1, i)
}
fmt.Println("after append 10 elems, length:", len(slice1), ", capacity:", cap(slice1))
for _, num := range slice1 {fmt.Printf("%d ", num)
}
fmt.Println("\n")
nums2 := [10]int {1, 2, 3, 4, 5}
slice2 := nums2[:4] //初始化2 左閉右開 0 - 3 size 4 cap 10
slice3 := nums2[1:] //初始化3 左閉右開 1 - 10 size 9 cap 9
slice4 := nums2[0:4:5] //初始化4 左閉右開 0 - 3 size 4 cap 5(5 - 0)
slice5 := nums2[:] //初始化5 左閉右開 0 - 10 size 10 cap 10
fmt.Println("slice2 length:", len(slice2), ", capacity:", cap(slice2))
fmt.Println("slice3 length:", len(slice3), ", capacity:", cap(slice3))
fmt.Println("slice4 length:", len(slice4), ", capacity:", cap(slice4))
fmt.Println("slice5 length:", len(slice5), ", capacity:", cap(slice5))
slice6 := make([]int, 0, 10) //初始化6 size 0 cap 10
var slice7 = make([]int, 0, 10) // 初始化7 size 0 cap 10
var slice8[]int = make([]int, 0, 10) // 初始化8 size 0 cap 10
fmt.Println("slice6 length:", len(slice6), ", capacity:", cap(slice6))
fmt.Println("slice7 length:", len(slice7), ", capacity:", cap(slice7))
fmt.Println("slice8 length:", len(slice8), ", capacity:", cap(slice8))
}
運(yùn)行效果
切片本質(zhì)上就是指向底層的數(shù)組 可以是一開始就生成切片對象 也可以是生成了數(shù)組后 再在切片上面切
如果剛開始切片是基于數(shù)組 那么修改切片 本質(zhì)就是修改數(shù)組 數(shù)組和切片共享的是同一塊內(nèi)存
而如果當(dāng)切片append擴(kuò)容后 超過了之前的切片的capacity 此時就會像vector
一樣 另外找一塊內(nèi)存地址 并且將當(dāng)前的內(nèi)容復(fù)制過去 此時切片其實本質(zhì)和之前的數(shù)組就已經(jīng)沒關(guān)系了 下面例子可以很清晰的表示
111.go
package main
import (
"fmt"
)
func main() {nums := [...]int {1, 2, 3, 4, 5}
slice := nums[:]
fmt.Println("before append, slice length:", len(slice), ", capacity:", cap(slice))
fmt.Println("before modify:")
for index, num := range nums {fmt.Printf("nums2[%d]:%d slice[%d]:%d\n", index, num, index, slice[index])
}
for i := 0; i< len(nums); i++ {slice[i] = i + 100
}
fmt.Println("after modify:")
for index, num := range nums {fmt.Printf("nums2[%d]:%d slice[%d]:%d\n", index, num, index, slice[index])
}
slice = append(slice, 0)
fmt.Println("after append, slice length:", len(slice), ", capacity:", cap(slice))
for i := 0; i< 5; i++ {slice[i] = i + 10
}
for index, num := range nums {fmt.Printf("nums2[%d]:%d slice[%d]:%d\n", index, num, index, slice[index])
}
}
運(yùn)行效果
切片的length表示 當(dāng)前切片中實際存在的長度
切片的cap表示 當(dāng)前切片可擴(kuò)容的長度
切片如果基于 cap 可以擴(kuò)容 當(dāng)length == cap時 擴(kuò)容則是2倍擴(kuò)容
擴(kuò)容底層有機(jī)制 后面我再詳細(xì)看看
但是如果切片基于其他切片 則cap大只能是其他切片的cap 無法額外分配內(nèi)存擴(kuò)容
獲取切片的length是由len()獲取 capacity是由cap()獲取
如果是空切片 例如用var slice1 []int
生成切片
則為Nil
切片 切片僅僅能和Nil
切片作比較 不能與其他切片做比較
111.go
package main
import "fmt"
func main() {var slice1 []int
if slice1 == nil {fmt.Println("Nil Slice")
} else {fmt.Println("Non-Nil Slice")
}
}
運(yùn)行效果
切片使用范圍更多 當(dāng)作vectorappend
添加元素
二維切片[][]string{}
slice := [][]string{}
slice = append(slice, []string{})
fmt.Println(len(slice[0]), cap(slice[0]))
對于切片或者有序序列
可以Range
用法如下 可用_
代替range不用的值
package main
import "fmt"
func main() {slice := [][]string{}
slice = append(slice, []string{})
for index, str := range slice {fmt.Println(index, str)
}
for _, str := range slice {fmt.Println(str)
}
for index, _ := range slice {fmt.Println(index)
}
}
就像是c++
中的map
底層是用紅黑樹實現(xiàn)的
初始化map的方式map[key_type]value_type
111.go
package main
import "fmt"
func main() {map_ := map[string]int{}
var m = make(map[string]int)
map_["gogo"] = 1
map_["thanks"] = 2
m["gogo"] = 1
m["thanks"] = 2
fmt.Println(map_["gogo"], map_["thanks"])
fmt.Println(m["gogo"], m["thanks"])
}
下面的操作包括 插入值 刪除值 查找值
package main
import "fmt"
func main() {map_ := map[string]int{}
map_["gogo"] = 1
map_["thanks"] = 2
elem, ok := map_["gogo"]
fmt.Println(elem, ok)
elem, ok = map_["go"]
fmt.Println(elem, ok)
map_["gogo"] = 3
elem, ok = map_["gogo"]
fmt.Println(elem, ok)
delete(map_, "gogo")
elem, ok = map_["gogo"]
fmt.Println(elem, ok)
}
運(yùn)行效果
函數(shù)可以生成為類似于c++
的可執(zhí)行函數(shù)對象 或者可以捆綁的執(zhí)行函數(shù)對象
package main
import "fmt"
func mul(x int, z int) int {return x * z
}
func mulfunc(func_ func(int, int) int, z int) int {return func_(3, 5) * z
}
func main() {funcobj := func(x, y int) int {return x * y
}
fmt.Println(funcobj(2, 3))
fmt.Println(mul(funcobj(2, 3), 20))
fmt.Println(mulfunc(funcobj, 20))
}
運(yùn)行效果
剛剛仔細(xì)去看了一下 發(fā)現(xiàn)并沒有那么好理解
用我的話來解釋一下 閉包內(nèi)部聲明的參數(shù) 其參數(shù)的聲明期是和函數(shù)閉包對象的生命期一樣的
并且返回一個匿名函數(shù) 之后匿名函數(shù)也可以使用之前聲明的函數(shù)對象
下面是簡單的使用例子 后續(xù)復(fù)雜的使用還要再琢磨琢磨111.go
package main
import "fmt"
func add() func() int {i := 0
return func() int {i += 1
return i
}
}
func deleter(x int) func(x int) int {i := 100
return func(x int) int {i -= x
return i
}
}
func main() {Adder := add()
fmt.Println(Adder())
fmt.Println(Adder())
Deleter := deleter(10)
fmt.Println(Deleter(20))
fmt.Println(Deleter(30))
}
運(yùn)行效果
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧