0.基本語法結構
package main
import "fmt"
func main(){
fmt.Println("Hello World")
}
- 聲明包
- 保留了大括號,但去掉了分號
- 和python有點像,但沒有強制鎖進
- 首字母大寫表示public,小寫表示private
- 和類c語言相似,都是從main函數開始執行
1、 變量
變量的聲明和初始化
go語言的變量聲明需要使用var
一下,或者使用海象運算符
var x int =1 //長聲明
var y,z int =1024,2048 //多重聲明
p:=3 //海象運算符,短聲明
//如果沒有初始化,用默認值代替
const Pi=3.14 //常量,變量不可更改。聲明常量需要關鍵字const,禁止使用海象運算符
變量類型
go是強類型語言,對于數值類型的定義域和符號分的很清,除了所有語言都有的數字類型、字符串、數組外,還有一些go獨有的派生類型。
整數類型:int,int8,int32,int64,帶符號和不帶符號
浮點類型:Float32—單精度浮點值,Float64—雙精度浮點值
布爾類型:true,false
字符串類型:string
數組類型:array
指針類型:pointer
管道類型:chan
接口類型:interface
常量
const PI =3.1415926
2 、運算符
//算術運算符
x,y :=1,2
res:=x+y //加法
res:=x-y //減法
res:=x/y //除法,取整
res:=x%y //模,取余數
res+=x //賦值運算符,類似的*=,%=
//關系運算符
res:=x==y
res:=x!=y
res:=x>y
res:=x<y
//邏輯運算符
res:=x>0&&y>=0 //與門
res:=x>0||y>0 //或門
res:=!(x>y)//非門
3、 邏輯結構
判斷
//判斷語句
x:=1
if x>0{
//... ...
}else{
//... ...
}
循環
//for循環
for x:=1;x<10;x++{
//...
}
// 省略初始化和迭代loop
x:=1
for x<10{
//...
x++
}
switch
//switch,注意go中沒有break語句,遇到第一個匹配的case就會跳出判斷,不會穿透
x:=1
switch x{
case 1:
//...
case 2:
//...
case 3:
//...
default:
//...
}
4、函數
函數結構
關鍵字、函數名、函數體、輸入參數,返回值
//基本結構,關鍵字、函數名、函數體、形參、返回值
func FunName(v int) string{
return st
}
//多個參數的輸入和輸出
func FunName(v1 int ,v2 int)(int,string){
return 2,"2"
}
可變參數
// 例子:求n個整數的和
func sum(x ...int) (s int) {
//可變參數
for _, v := range x {
s += v
}
return
}
// 也可以直接把切片扔進去作為可變參數
arr=[3]int{1,2,3}
sum(arr...) //類似于解包的操作
閉包于匿名函數
閉包給了在內部函數捕獲外部函數參數的權利,匿名函數是閉包的實現方式之一,字面意思上的沒有名字,直接調用的函數。
// 函數的閉包
func test14(a int, b int) int {
func() {
fmt.Println(a, b)
}()
return a + b
}
5、指針
指針,即一個值的內存地址。在go中,&
表示取地址,*
表示取值。
指針聲明
var p1 *int
var p2 *string
// go中指針必須帶類型
6、結構體
定義數據使用,類似于其他面向對象語言中的class
type Contact struct{
Age int
Name string
}
結構體與指針
x:=&Contact{"ronron",12}
x.name="xiaojiji"
7、方法
結構體除了聲明了屬性外,還能定義方法,方法即帶接收器的函數。
type Contact struct{
Name string
Age int
}
// 方法,結構體接收器
func (c Constact) addAge1(){
c.Age+=1
}
// 方法,結構體指針接收器
func (c *Contact) addAge2(){
c.Age+=1
}
與普通函數相比,方法多了一個接收器,這個接收器可以是結構體,也可以是結構體指針。如果是結構體,那么傳遞的是結構體副本,修改不會影響原有的對象。如果是結構體指針,那么會影響原有的對象。
8、數組 Array
var a [3]int //定義一個長度為3的空數組
var a [3]int{1,2,3} //定義一個長度為3的數組并初始化
//數組的操作
// 索引
a[1]
數組一旦定義就無法修改大小,不方便使用,所以常用切片 slice代替
//切片定義方式一,直接從數組中切下來
a :=[5]int{1,2,3,4,5}
b:=a[1,3]
//切片定義方式二 ,使用make方法
c:=make([]int,5,10) //注意初始化長度為5,元素默認為0
//切片的遍歷,和python真的相似
for i := 0; i < len(a); i++ {
fmt.Println(a[i])
}
for _, v := range a {
fmt.Println(v)
}
切片
go語言中的數組一旦定義就不能再改變長度,不大好用。切片是數組的高一級別的抽象,可以理解為動態數組。
// 定義一個字符串的切片,初始長度為10,容量為20
s:=make([]string 10,20)
// 切片的索引,與python相似
s[1:3]
//
9、字典Map
//直接定義和初始化map
m := map[string]int{
"a": 1,
"b": 2,
}
// 使用make進行初始化
m :=make(map[string]int)
// 添加元素
m["c"]=1024
//獲取value
value,ok:=m["c"]
value,ok:=m["d"]
if ok{
}else{
}
//遍歷map
for k, v := range m {
fmt.Println(k, v)
}
//刪除dict元素
delete(m,"a")
10、并發
并發是go語言提供的核心語法,相比其他語言多線程的方式,使用簡單,效率更高,管理便捷。
go例程中最核心的概念是goroutine和chan
goroutine
// 任務1
func A(){
//do some thing a
}
//任務2
func B(){
// do some thing b
}
//關鍵字go 直接使用例程,類似于其他語言中開辟一個新的線程
func main(){
go A() //處理任務A
go B() //處理任務B
}
channel
Channel用于多個goroutine 之間進行通信,<-
符合指示數據的流動方向
// 創建一個channel
ch:=make(chan int)
// 向chan中發射數據
ch <- 1
// 從chan中接受一個數據
value := <-chan
// 不用變量接收也可以
<- chan
11 錯誤處理
go中沒有exception的概念,取而代之的是error,error在go中是一個接口
type error interface {
Error() string //只要實現了這個方法,就算error
}
go中把‘異常’當中一個值來處理,所以并沒有try catch的語法,而是通過判斷error是否為nill來進行異常處理。
// 內部error的處理
func ErrorTest(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("b can not be zero")
}
return a / b, nil
}
// 調用
v,error:=ErrorTest(1,0)
if error !=nill{
// 處理有錯誤的情況
return
}
//...正常的處理
Panic和recove
panic用于手動拋出致命異常,直接宕機,程序線程停止。
recover 獲取宕機時的信息,配合defer關鍵字,讓程序在宕機后能繼續從斷點處開始運行。