兵長:喲,最近在幹啥呢golang
胖sir:在看我以前的go基礎學習資料呢,回顧一下api
兵長:那給我分享一下唄,我也想回顧回顧數組
胖sir:用你的小手指點開你的手機,我來傳給你安全
兵長:你信不信個人小手指能夠帶你飛整個峽谷 . . .數據結構
package main import "fmt" func main(){ //go語言中此處的花括號不能單獨佔一行,不然會報錯 fmt.Println("hello world") }
go語言一條語句佔一行,若是一行須要執行多個語句 使用 分號 隔開併發
go語言的輸出語句有3種方式app
下面列舉了 Go 代碼中會使用到的 25 個關鍵字或保留字:ide
break | default | func | interface | select |
---|---|---|---|---|
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
除了以上介紹的這些關鍵字,Go 語言還有 36 個預約義標識符:函數
append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
---|---|---|---|---|---|---|---|---|
copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new | nil | panic | uint64 |
println | real | recover | string | true | uint | uint8 | uintptr |
定義變量的三種方式學習
//字符串 可使用+ 進行拼接 fmt.Println("this is my func") fmt.Println("hello ,wolrd" + "xiaozhuzhu") //定義變量 var name string="xiaomotong" var age,tail int=24,170 fmt.Println(name, age , tail) fmt.Println(name) fmt.Println(age) fmt.Println(tail) //定義變量的三種方式 //1 var a int = 1 fmt.Println(a) //2 使用var定義變量,可是不定義類型,經過賦初值的方式,go編譯器自動識別 var b = "hello" fmt.Println(b) //3 使用:=的方式來進行 新變量的定義,僅限於新變量 //:= 左側若是沒有聲明新的變量,就產生編譯錯誤 c := 20 fmt.Println(c) //c:=30 //報錯,由於c已經不是新變量的 c=30 //正確,是一個正常的賦值操做 fmt.Println(c) c,d:=40,90 //這樣是合法的 fmt.Println(c,d)
因式分解的方式,僅僅適用於定義全局變量
//因式分解的方式,僅僅適用於定義全局變量 var ( g_a int = 1 g_b,g_c int=1,2 )
空白標識符 _ 也被用於拋棄值,如值 5 在:_, b = 5, 7 中被拋棄。
_ 其實是一個只寫變量,你不能獲得它的值。這樣作是由於 Go 語言中你必須使用全部被聲明的變量,但有時你並不須要使用從一個函數獲得的全部返回值。
//空白符 _,e := 2,3 fmt.Println(e)
//定義const常量 const width,height = 10,5 var area int=width*height fmt.Println("面積爲", area) //50
const( unknow = 0 man = 1 woman = 2 ) println(unknow,man,woman) //0 1 2
const( a = "hello" b = len(a) c = unsafe.Sizeof(a) ) println(a,b,c) //hello 5 16
iota,特殊常量,能夠認爲是一個能夠被編譯器修改的常量。
iota 在 const關鍵字出現時將被重置爲 0(const 內部的第一行以前),const 中每新增一行常量聲明將使 iota 計數一次(iota 可理解爲 const 語句塊中的行索引)。
iota 能夠被用做枚舉值:
//itoa的用法 const( g_a = iota g_b g_c g_d ) const( g_e = iota g_f = "hello" g_g g_h = iota g_i ) const( g_j = 1<<iota g_k g_l g_m ) println(g_a,g_b,g_c,g_d) println(g_e,g_f,g_g,g_h,g_i) println(g_j,g_k,g_l,g_m) //0 1 2 3 //0 hello hello 3 4 //1 2 4 8
go語言的運算符和C語言的運算符基本一致
算術運算符
關係運算符
邏輯運算符
位運算符
賦值運算符
其餘運算符
if xxx { ... }
if xxx{ ... }else{ ... }
if xxx{ if xxx { ... } ... }
package main import "fmt" func main(){ grade:= 90 if grade >= 90{ println("優秀") }else if grade >=70 && grade <90{ println("良好") }else{ println("差") } var x interface{} //計算類型 switch i := x.(type){ case nil: fmt.Printf(" x 的類型 :%T\n",i) case int: fmt.Printf("x 是 int 型") default: println("未知") } }
select
相似於C語言中的select,用於多路IO複用
package main import "fmt" func main(){ //相似C語言中的for var sum int for i:=1;i<=10;i++{ sum +=i } fmt.Println(sum) //相似於while for sum >30{ sum -= 10 fmt.Println(sum) } //死循環 for { ... }
//for-each range 循環的方式 name := []string{"qqq","yyy"} for i,str:= range name{ fmt.Printf("%d -- %s\n",i,str) } //0 -- qqq //1 -- yyy ------------------------------------------------------------------------ str := []string{"北京", "天津", "山東"} //能夠默認丟掉第二個返回值 for i := range str { fmt.Printf("%d -- %s\n", i, str[i]) }
go語言的函數,能夠有多個返回值,其他和C語言沒有什麼區別
與C語言一致
思想和C語言一致,數組是固定長度的
切片是動態擴容的,相似於C++的vector
切片寫法以下:
name := []string{"xiaomotong","pangsir"} nums :=[]int{1,2,3,4,5,6}
var ptr1 *int
var a int var ptr *int var pptr **int ptr = &a pptr = &ptr
var ptr [5]*int
go語言中的結構體變量,和結構體指針,訪問結構體成員的時候,都是使用 點(.)來進行訪問,以下:
//定義一個結構體 type info struct{ name string age int height int } //使用 var stu info stu.name = "xiaomotong" stu.age = 24 stu.height = 170 fmt.Println(stu.name,stu.age,stu.height) var stu2 *info = &stu stu2.name = "pangsir" stu2.age = 24 stu2.height = 160 fmt.Println(stu2.name,stu2.age,stu2.height)
Go 語言切片是對數組的抽象。
Go 數組的長度不可改變,在特定場景中這樣的集合就不太適用,Go中提供了一種靈活,功能強悍的內置類型切片("動態數組"),與數組相比切片的長度是不固定的,能夠追加元素,在追加時可能使切片的容量增大。
package main /* author:xiaomotong file:slice function:study slice for golang */ import "fmt" func main(){ //定義切片的方式 //一、使用var定義 var s1 = []int{1,2,3}; printInfo(s1); //二、定義空slice var s2 []int printInfo(s2); //三、使用:=定義 ss := []int{3,4,5,6} printInfo(ss); //四、使用make來定義 make([]type,len,cap) s3 := make([]int,2,3) printInfo(s3); //複製操做 s3[0] = 3 printInfo(s3); //覆蓋整個slice s1 = s3 printInfo(s1); //apend 和 copy的使用 s3 = append(s3,6,7,8,9) printInfo(s3); //擴容 s4 := make([]int,len(s3),cap(s3) * 3) copy(s4,s3) printInfo(s4); //s[2:] println(s4[1:]) println(s4[:4]) println(s4[1:3]) fmt.Printf("s4[1:] = %v \n",s4[1:]) fmt.Printf("s4[:4] = %v \n",s4[:4]) fmt.Printf("s4[1:3] = %v \n",s4[1:3]) } func printInfo(s[]int){ fmt.Printf("len = %d, cap = %d, slic = %v\n",len(s),cap(s),s); }
Go 語言中 range 關鍵字用於 for 循環中迭代數組(array)、切片(slice)、通道(channel)或集合(map)的元素。
在數組和切片中它返回元素的索引和索引對應的值,在集合中返回 key-value 對。
package main /* author:xiaomotong file:range function:study range for golang */ import "fmt" func main(){ //一、range 對於 數組、切片 s := []string{"apple","pen"} for i,value := range s{ fmt.Println(i,value) } //二、對於字符串 for i,value := range "hello"{ fmt.Println(i,value) } //三、range對於map集合 m := map[string]string{"name":"xiaopang","age":"25"} for i,value := range m{ fmt.Println(i,value) } //四、佔位符_ sum := 0 nums := []int{1,2,3,4,5} for _,value := range nums{ sum += value } fmt.Println(sum) }
Map 是一種無序的鍵值對的集合。Map 最重要的一點是經過 key 來快速檢索數據,key 相似於索引,指向數據的值。
Map 是一種集合,因此咱們能夠像迭代數組和切片那樣迭代它。不過,Map 是無序的,咱們沒法決定它的返回順序,這是由於 Map 是使用 hash 表來實現的。
//相似於key-value的形式 map[string]string m := map[string]string{"name":"xiaozhu","age":"15"} mm := make(map[string]string) countryCapitalMap [ "France" ] = "巴黎" countryCapitalMap [ "Italy" ] = "羅馬" countryCapitalMap [ "Japan" ] = "東京" countryCapitalMap [ "India " ] = "新德里"
delete() 函數用於刪除集合的元素, 參數爲 map 和其對應的 key
delete(countryCapitalMap,"France")
Go 語言支持遞歸。但咱們在使用遞歸時,開發者須要設置退出條件,不然遞歸將陷入無限循環中。
遞歸函數對於解決數學上的問題是很是有用的,就像計算階乘,生成斐波那契數列等。
遞歸算階乘
package main import "fmt" func fabulaxiaomotong(n uint 64) (result uint64){ if n>0 { return fabulaxiaomotong(n-1)*n } return 1 } func main(){ fmt.Println("result : ",fabulaxiaomotong(15)) }
菲波拉契數列
func fabolaxiaomotong(n uint64)(result utin64){ if n<2{ return n }else{ return fabolaxiaomotong(n-2)+fabolaxiaomotong(n-1) } }
Go 語言提供了另一種數據類型即接口,它把全部的具備共性的方法定義在一塊兒,任何其餘類型只要實現了這些方法就是實現了這個接口
package main import "fmt" //接口 type phone interface { call() show() } type xiaomi struct { name string ads string } type huawei struct { name string ads string } //接口實現 func (x xiaomi) call() { fmt.Println("phoneName :", x.name) } func (x xiaomi) show() { fmt.Println("advertisement :", x.ads) } func (h huawei) call() { fmt.Println("phoneName :", h.name) } func (h huawei) show() { fmt.Println("advertisement :", h.ads) } func main() { x := xiaomi{"mi note2", "for fire"} x.call() x.show() h := huawei{"hw p40", "your better phone"} h.call() h.show() }
Go 語言經過內置的錯誤接口提供了很是簡單的錯誤處理機制。error類型是一個接口類型,這是它的定義:
package main import "fmt" //定義數據結構 type DivideError struct { devidee int devider int } //錯誤處理實現Error()接口 func (de *DivideError) Error() string { strdata := ` error,divide is zero dividee is %d divider is zero ` return fmt.Sprintf(strdata, de.devidee) } //實現功能接口 func Divide(dividee int, divider int) (result int, errMsg string) { if divider == 0 { data := DivideError{dividee, divider} errMsg = data.Error() return } else { return dividee / divider, "" } } func main() { a := 10 b := 0 result, err := Divide(a, b) if err != "" { fmt.Println(err) return } fmt.Printf("%d / %d == %d \n", a, b, result) }
Go 語言支持併發,咱們只須要經過 go 關鍵字來開啓 goroutine 便可。goroutine 是輕量級線程,goroutine 的調度是由 Golang 運行時進行管理的。goroutine 語法格式:
package main import ( "fmt" "time" ) func say(s string) { var i int for i = 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } var num int = 0 //goroutine 是線程不安全的 func countNum() { var i int for i = 0; i < 10; i++ { time.Sleep(5 * time.Millisecond) num++ } } func main() { //go say("hello") //say("world") go countNum() countNum() fmt.Println(num) }
通道(channel)是用來傳遞數據的一個數據結構。通道可用於兩個 goroutine 之間經過傳遞一個指定類型的值來同步運行和通信。操做符 <- 用於指定通道的方向,發送或接收。若是未指定方向,則爲雙向通道。
通道能夠設置緩衝區,經過 make 的第二個參數指定緩衝區大小
Go 經過 range 關鍵字來實現遍歷讀取到的數據,相似於與數組或切片
package main import "fmt" //不帶緩衝的 通道 func getSum(s []int, c chan int) { sum := 0 for _, value := range s { sum += value } c <- sum } func getSum2(c chan int, n int) { x, y := 0, 1 var i int for i = 0; i < n; i++ { c <- x x, y = y, x+y } close(c) //關閉通道 } func main() { //不帶緩衝的 通道 // s := []int{3, 5, -2, 3, 4, 7, 1, 1, 1} // c := make(chan int) // go getSum(s[:3], c) // go getSum(s[3:6], c) // go getSum(s[6:], c) // x, y, z := <-c, <-c, <-c // fmt.Println(x, y, z, x+y+z) //帶緩衝的通道 c := make(chan int, 10) go getSum2(c, cap(c)) for value := range c { fmt.Println(value) } }
本身調用別人的包或者本身的包,如上目錄結構
mylib.go
package mylib func Add(a, b int) int { return a + b }
main.go
package main import ( "fmt" "mystudy/mylib" ) func main() { fmt.Println(mylib.Add(2, 3)) }
以上爲本期所有內容,若有疑問能夠在評論區或後臺提出你的疑問,咱們一塊兒交流,一塊兒成長。
好傢伙要是文章對你還有點做用的話,請幫忙點個關注,分享到你的朋友圈,分享技術,分享快樂
技術是開放的,咱們的心態,更應是開放的。擁抱變化,向陽而生,努力向前行。
做者:小魔童哪吒