本期將go中的基礎語法模組通過程式碼的方式寫了一遍。
上傳到了github.後續將不斷通過更新專案總結go的學習以及總結。
下面的語法講解轉自golang官網,我簡寫了程式碼事例程式碼
golang官網:https://golang.google.cn/ref/spec
golang開源社群:http://tour.studygolang.com/welcome/1
程式碼地址:https://github.com/A1len/study-go
導讀
- 基礎語法
- 流程控制語句
基礎語法
這一部分將對go中的包、函式、申明變數、基本資料型別、常量做一個描述
包
Go程式是通過將程式包關聯在一起而組成。一個包又由一個或多個go原始檔組成,這些原始檔一起宣告瞭屬於該包的常量,型別,變數和函式,並且可以在同一包的所有檔案中進行訪問。這些元素可以 匯出並在另一個包中使用。
import (
"fmt"
"math"
)
//1.通過import的方式匯入包,可以像java一樣多個imprt匯入
//也可以通過上述方式
//2.在匯入了一個包之後,就可以用其匯出的名稱來呼叫它。
//在 Go 中,首字母大寫的名稱是被匯出的。
//Foo 和 FOO 都是被匯出的名稱。名稱 foo 是不會被匯出的。
//執行程式碼。然後將 math.pi 改名為 math.Pi 再試著執行一下
func main() {
fmt.Println(math.Pi)
}
函式
函式宣告將識別符號func繫結到函式。
package main
import ("fmt" "unsafe")
//函式可以返回一個或者多個值,具體看add和multipl函式
//兩個或多個連續的函式命名引數是同一型別,可以只需要最後一個引數定義型別
//Go 的返回值可以被命名,並且像變數那樣使用。
//返回值的名稱應當具有一定的意義,可以作為文件使用
//沒有引數的 return 語句返回結果的當前值。也就是`直接`返回
func add(x int, y int)(int){
return x+y
}
func multiple(x , y int)(string ,int){
return "hello",x
}
func multiple2(x , y int)(str string ,z int){
str="hello"
z=x
return
}
//外部實現,這裡其實可以不定義結構體
//後續補充go:linkname
func FlushICache(begin,end int)
func main() {
x ,y :=multiple(42, 13)
fmt.Print(x,y)
}
申明變數和常量
申明變數可以通過var或者:= 常量使用const
package main
import "fmt"
//go當中宣告一個變數可以通過var或者:=
//var可以作用在函式中也可以函式外
//:=只可以在函式中
//go有自動型別推斷,如果有初始值,可以不帶上變數型別
var initname="allen"
var name ,motherland string
var defaultvar string
//常量的定義和變數類似,只是換成了const來申明
const Pi = 3.14
func main() {
var num int
age:=18
fmt.Println(defaultvar,num,age)
}
基本資料型別
package main
import (
"math/cmplx"
"fmt"
)
/*
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
//一般需要用多大的可以選擇多大的數字型別
//如果沒有選擇將會按照作業系統選擇
//比如64位就會走int64
//go語言中的基礎資料型別都有預設值,
//這很正常引用指標得指向一個記憶體空間,才算初始化了一個變數
//否則一個指標不初始化,很容易造成基礎資料型別空指標。。。有點尷尬
byte // uint8 的別名
rune // int32 的別名,因為unicode是動態的所以選擇32位可以完全滿足,
新版本java對於這一塊做了自動判斷,節省空間
float32 float64
complex64 complex128
*/
var (
ToBe bool = false
MaxInt uint64 = 1<<64 - 1
z complex128 = cmplx.Sqrt(-5 + 12i)
)
func main() {
const f = "%T(%v)\n"
fmt.Printf(f, ToBe, ToBe)
fmt.Printf(f, MaxInt, MaxInt)
fmt.Printf(f, z, z)
}
流程控制語句
這部分沒有全部列出來只是舉了幾個典型例子以及常用的說明,具體可以看官網
for
for的用法和java中基本一樣,並且go裡面是沒有while了的
package main
import "fmt"
//for的使用和java中基本是一樣的,只是少了一個()
//並且go當中沒有while,使用for實現
//java中Doug Lea很喜歡這種寫法
func main() {
sum := 0
for i := 0; i < 10; i++ {
sum += i
}
fmt.Println(sum)
i := 1
for i < 1000 {
i += i
}
fmt.Println(i)
for {
break
}
}
switch
switch的變化比較多,沒有條件的 switch 同 switchtrue一樣。這一構造使得可以用更清晰的形式來編寫長的 if-then-else 鏈 switch用法比java更方便靈活,不用顯示的在語句中加break 如果要實現類似java的一個case成立繼續執行後續的case可以使用fallthrough
package main
import (
"fmt"
"runtime"
"time"
)
//switch用法比java更方便靈活,不用顯示的在語句中加break
//如果要實現類似java的一個case成立繼續執行後續的case可以使用fallthrough
//case也可以直接使用判斷語句
//以及type switch
//todo 後續看一下switch的實現原始碼
//感覺java的swtich語法糖和go比起來還是較弱,這也是java的歷史原因
func main() {
fmt.Print("Go runs on ")
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X.")
//fallthrough 開啟註釋看看結果
case "linux":
fmt.Println("Linux.")
//fallthrough
default:
// freebsd, openbsd,
// plan9, windows...
fmt.Printf("%s.", os)
}
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("Good morning!")
case t.Hour() < 17:
fmt.Println("Good afternoon.")
default:
fmt.Println("Good evening.")
}
var a interface{}
a = "abc"
switch t := a.(type) {
case string:
fmt.Printf("string %s\n", t)
case int:
fmt.Printf("int %d\n", t)
default:
fmt.Printf("unexpected type %T", t)
}
}
defer
defer 語句會延遲函式的執行直到上層函式返回。延遲呼叫的引數會立刻生成,但是在上層函式返回前函式都不會被呼叫 可以理解為先進後出
package main
import (
"fmt"
)
//defer的操作其實是一個壓棧的方式呼叫
//先進後出FILO
//可以一次執行下面的三個例子
//另外通過例子3其實可以知道defer是有資料拷貝的
//換句話說執行defer的時候資料就儲存了一個份
//後續變數怎麼改變defer還是輸出同樣的資訊
//TODO defer的使用場景後續補充,暫時先當try catch finally使用
func main() {
fmt.Println("counting")
a:="hello world"
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
//1.os.Exit(0)//直接推出不會執行defer
//2.return//遇到return才返回
defer fmt.Println(a)
//3.a="hello defer"
fmt.Println("done")//沒有return則執行到底
}
最後各位可以掃下方二維碼關注我公眾號,基本每週會推送一到兩篇的go學習記錄,後續學完基礎語法,會準備寫一個go微服務專案,原始碼依然放在github上面。
本作品採用《CC 協議》,轉載必須註明作者和本文連結