Golang 下載
安裝包鏈接:https://share.weiyun.com/InsZoHHu
IDE 下載:https://www.jetbrains.com/go/
第一個 golang 程序
package mainimport "fmt"func main() {fmt.Println("hello golang")
}
每個可執行代碼都必須包含 Package、import 以及 function 這三個要素。
變量
主函數文件:
package mainimport ("awesomeProject/package1""fmt"
)// 全局變量
var gStr string
var gInt intfunc main() {// 局部變量var lStr stringvar lInt intgStr = "out"gInt = 100lStr = "in"lInt = 50fmt.Println(gStr)fmt.Println(gInt)fmt.Println(lStr)fmt.Println(lInt)// 包外函數package1.Fun()// 包外變量package1.Str = "good"fmt.Println(package1.Str)
}
package1 包的文件:
package package1import ("fmt"
)var Str stringfunc Fun() {fmt.Println("test")
}
注意:golang是以首字母大小寫來區分對包外是否可見。
所以 Fun() 函數,Str,想要在 main 文件被訪問,都首字母大寫了。
數組,切片,字典
package mainimport "fmt"func main() {//數組初始化var strAry = [10]string{"aa", "bb", "cc", "dd", "ee"}//切片初始化var sliceAry = make([]string, 0)sliceAry = strAry[1:3]//字典初始化var dic = map[string]int{"apple": 1,"watermelon": 2,}// %v 是按照默認格式輸出fmt.Printf("strAry %+v\n", strAry)fmt.Printf("sliceAry %+v\n", sliceAry)fmt.Printf("dic %+v\n", dic)
}
切片通過索引的方式指向了數組。切片是可以更改某個元素內容的,數組則不能,在開發中,主要都是使用切片來進行邏輯處理。
條件判斷語句
package mainimport "fmt"func main() {// 可以通過 := 這種方式直接初始化基礎變量localStr := "case3"if localStr == "case3" {fmt.Printf("into ture logic\n")} else {fmt.Printf("into false logic\n")}//字典初始化var dic = map[string]int{"apple": 1,"watermelon": 2,}// 用于檢查字典中某個鍵是否存在,如果存在 num 取鍵值,ok 取 true,反之 ok 取 falseif num, ok := dic["orange"]; ok {fmt.Printf("orange num %d\n", num)}if num, ok := dic["watermelon"]; ok {fmt.Printf("watermelon num %d\n", num)}switch localStr {case "case1":fmt.Println("case1")case "case2":fmt.Println("case2")case "case3":fmt.Println("case3")default:fmt.Println("default")}
}
循環
package mainimport "fmt"func main() {for i := 0; i < 5; i++ {fmt.Printf("i = %d ", i)}fmt.Println("")j := 0for {if j == 5 {break}fmt.Printf("j = %d ", j)j++}fmt.Println("")// 可以指定初始個數也var strAry = []string{"aa", "bb", "cc", "dd", "ee"}//切片初始化var sliceAry = make([]string, 0)sliceAry = strAry[1:3]for i, str := range sliceAry {fmt.Printf("slice i %d, str %s ", i, str)}fmt.Println("")//字典初始化var dic = map[string]int{"apple": 1,"watermelon": 2,}for k, v := range dic {fmt.Printf("key %s, value %d\n", k, v)}
}
range 關鍵字用于迭代切片、數組、字典等可迭代的數據結構。
協程
package mainimport ("fmt""time"
)func a() {time.Sleep(3 * time.Second)fmt.Println("it's a")
}func b() {time.Sleep(2 * time.Second)fmt.Println("it's b")
}func c() {time.Sleep(1 * time.Second)fmt.Println("it's c")
}func main() {go a()go b()go c()time.Sleep(5 * time.Second)
}
只要使用關鍵字 go 就能讓 a,b,c 三個函數并發運行。
通道(channel)
通道的要點:
1.類似 Linux 中管道(pipe),先進先出; 2.線程安全,多個 goroutine 同時訪問,不需要加鎖; 3.channel 是有類型的,一個整數的 channel 只能存放整數。
通道的定義:
var ch0 chan int
var ch1 chan string
var ch2 chan map[string]stringtype stu struct{}var ch3 chan stu
var ch4 chan *stu
通道可以用于協程之間數據的傳遞,一般分為有緩沖通道和無緩沖通道。
兩個協程間如果有數據交流,這時候就可以用通道來傳遞。
package mainimport ("fmt""time"
)var ch chan intfunc a() {time.Sleep(3 * time.Second)a := 5ch <- a // 發送操作fmt.Println("out of a")
}func b() {time.Sleep(1 * time.Second)fromA := <-ch // 接收操作b := fromA + 3fmt.Println("b is ", b)
}func main() {ch = make(chan int, 1)go a()go b()time.Sleep(20 * time.Second)fmt.Println("out of main")
}
- make(chan int, 1) 用于創建一個新的信道,其中 chan int 表示該信道用于傳輸整數類型的值。
- 逗號后的 1 是指定信道的緩沖大小。緩沖大小表示信道可以同時容納的元素個數。 在這種情況下,ch 是一個緩沖大小為 1 的信道,即最多可以同時容納一個整數值。
舉個例子:
創建緩沖信道時,當發送操作(ch <- value)發生時,如果緩沖區已滿,發送操作將被阻塞,直到有接收操作(value = <-ch)從緩沖區中讀取值。類似地,當接收操作(value = <-ch)發生時,如果緩沖區為空,接收操作將被阻塞,直到有發送操作(ch <- value)將值放入緩沖區。
chSync := make(chan int) // 無緩沖
chAsyn := make(chan int, 1) // 有緩沖
理解有緩沖和無緩沖:
同樣是向通道里塞一個數據:chSync <-1 無緩沖場景:一直要等有別的協程通過<-chSync接手了這個參數,那么chSync<-1才會繼續下去,要不然就一直阻塞著。 有緩沖場景:chAsyn<-1則不會阻塞,因為緩沖大小是1,只有當放第二個值的時候,第一個還沒被人拿走,這時候才會阻塞。 仔細理解下,實際這就是同步和異步的區別,無緩沖一定是同步等待,有緩沖只有在緩沖滿了,異步又處理不過來的時候,才會阻塞。
舉個例子:
無緩沖:
package mainimport ("fmt""time"
)var ch chan intfunc a() {time.Sleep(3 * time.Second)a := 5ch <- afmt.Println("out of a")
}func b() {time.Sleep(1 * time.Second)
}func main() {ch = make(chan int) // 無緩沖管道go a()go b()time.Sleep(20 * time.Second)fmt.Println("out of main")
}
輸出:
out of main
有緩沖:
package mainimport ("fmt""time"
)var ch chan intfunc a() {time.Sleep(3 * time.Second)a := 5ch <- afmt.Println("out of a")
}func b() {time.Sleep(1 * time.Second)
}func main() {ch = make(chan int, 1) // 有緩沖管道go a()go b()time.Sleep(20 * time.Second)fmt.Println("out of main")
}
輸出:
out of a
out of main
接口
package mainimport "fmt"// Shape 是接口
type Shape interface {Area() float64Perimeter() float64
}type Rect struct {height float64weight float64
}func (p *Rect) Area() float64 {return p.height * p.weight
}func (p *Rect) Perimeter() float64 {return 2 * (p.height + p.weight)
}func main() {var s Shape = &Rect{height: 10, weight: 8}fmt.Println(s.Area())fmt.Println(s.Perimeter())
}
代碼中Shape就是一個接口,聲明了兩個方法:面積(Area)和周長(Perimeter)。 咱們定義了一個具體結構 Rect,實現這個接口。可以看到,用基礎的 Shape 接口,可以一個指向 Rect 對象,并調用其方法。
Golang 只需要實現某個 interface 的全部方法,那么就是實現了該類型。所以,Golang的繼承關系是非侵入式的,這也是Golang的特色與優點。
webserver
用 http 裸寫:
package mainimport ("log""net/http"
)func SayHello(w http.ResponseWriter, r *http.Request) {w.Write([]byte("hello")) // 以字符串"hello"作為返回包
}func main() {http.HandleFunc("/say_hello", SayHello)err := http.ListenAndServe(":8080", nil) // 開啟一個http服務if err != nil {log.Print("ListenAndServe: ", err)return}
}
運行,然后就能訪問了:http://localhost:8080/say_hello
寫在最后:
以上就是本篇文章的內容了,感謝你的閱讀。
如果感到有所收獲的話可以給博主點一個贊哦。
如果文章內容有遺漏或者錯誤的地方歡迎私信博主或者在評論區指出~