Go語言基礎(chǔ)知識(一)

Go 語言學(xué)習(xí)的入門部分草讶,如果有C語言的基礎(chǔ)類比學(xué)習(xí)會非常迅速÷疲總結(jié)來說 Go語言 和 C語言很相似堕战,語法更為簡單,所以寫起來會相對迅速很多拍霜。以下是基礎(chǔ)語法的筆記践啄。

>教程來自 http://www.yiibai.com/go/go_start.html
感謝博主的精心編寫。

導(dǎo)入包

import "fmt"
import "math"

或者下面:

import (
    "fmt"
    "math"
)

導(dǎo)出名字

go 中沉御,首字母大寫名稱是被導(dǎo)出的屿讽。全小寫的名字是不會被導(dǎo)出。

fmt.Println(math.Pi)      //這里PI 改為 pi 就是不可以的吠裆。

函數(shù)

 func add(x int ,y int) int {
    return x + y
}

或者

func add(x,y int) int {
    return x + y 
}

函數(shù)中命名返回值

func split (sum int )(x,y int){
    x = sum * 4 /9 ;
    y = sum - x ;
    return ;
}

變量

變量定義看起來頗為隨意伐谈,很方便。

var c, python , java = true , false , "no!" 
var i , j int = 1 , 2 

func main(){
    fmt.Println(i,j,c,python,java)
}

變量在函數(shù)內(nèi)還可以去掉var等關(guān)鍵字试疙,直接退化為如下操作:

func main(){
    var i , j int = 1 , 2 
    k := 3
    c , python , java = true , false , "no!"
    fmt.Println(i,j,k,c,python,java)
}

基本數(shù)據(jù)類型

bool
string
int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64 uintptr
byte //uint8 別名
rune //int32 的別名
     //代表一個unicode碼
float32 float64
complex64 complex128

int,uint,uintptr在32位系統(tǒng)上是32位诵棵,而在64位系統(tǒng)上是64位。一般直接使用int就可以了祝旷。一般僅有特定理由才用定長整型或者無符號整型履澳。

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,z,z)
    fmt.Printf(f,MaxInt,MaxInt)
    fmt.Printf(f,ToBe,ToBe)
}

零值

變量在定義時候沒有明確的初始化時會賦值為零值.

數(shù)值類型為 **0**
布爾類型為 **false**
字符串為 ""  **空字符串**

package main
import "fmt"

func main(){
    var i int
    var f float64
    var b bool
    var s string
    fmt.Printf("%v %v %v %q\n",i,f,b,s)

}

類型轉(zhuǎn)換

表達式T(v)將值v轉(zhuǎn)換為類型T。

一些關(guān)于數(shù)值的轉(zhuǎn)換

var i int = 42
var f float64 = float64(i)
var u uint = uint(f)

//或者更為簡單的形式
i := 42
f := float64(i)
u := uint(f)

類型推導(dǎo)

在定義一個變量卻并不顯式指定其類型的時候(使用 := 語法或者 var =表達式語法),變量的類型由(等號)右側(cè)的值推導(dǎo)得出.

當右值定義了類型時候,新變量的類型與其相同:

var i int
j := i  // j也是一個int

當時當右邊包含了未指明類型的數(shù)字常量時候怀跛,新的變量就可能是int距贷、float64或complex128 。 這取決于常量的精度:

i := 42            //int
f := 3.142         //float64
g := 0.867 + 0.5i  //complex128

常量

常量的定義與變量類似吻谋,只不過使用 const 關(guān)鍵字忠蝗。

常量可以是字符、字符串漓拾、布爾或數(shù)字類型的值阁最。

常量不能使用 := 語法定義。

package main

import "fmt"

const Pi = 3.14

func main(){
    const World = "世界"
    fmt.Println("Hello",World)
    fmt.Println("Happy",Pi,"Day")
    
    const Truth = true
    fmt.Println("Go rules?",Truth)
}

數(shù)值常量

數(shù)值常量是高精度的值骇两。

一個未指定類型的常量由上下文來決定其類型速种。

也嘗試一下輸出 needInt(Big) 吧。(int 可以存放最大64位的整數(shù)低千,根據(jù)平臺的不同有時會更少配阵。)

const(
    Big   = 1  << 100
    small = Big >> 99
)

func needInt(x int) int {return x * 10 + 1}
func needFloat(x float64) float64 {
    return x * 0.1
}

控制流

for

Go 只有一種循環(huán)結(jié)構(gòu) --- for循環(huán)。這點和C比較相似。具體如下:

func main(){
    sum : = 0 
    for i := 0 ; i < 10 ; i++ {
       sum += i
    }
    fmt.Println(sum)
}

其中循環(huán)初始化語句和后置語句都是可選的:

func main(){
    sum := 1 
    for ; sum < 1000 ; {
        sum += sum 
    }
    fmt.Println(sum)
}

這里和C語言很相似闸餐,但是不需要括號饱亮,如果有括號反而會報錯矾芙。

for 也可以變成 C語言的中while

func main(){
    sum := 1
    for sum < 1000 {
        sum += sum
    }
    fmt.Println(sum)
}

或者變?yōu)樗姥h(huán)

func main(){
    for {    //無退出條件舍沙,變成死循環(huán)
    
    }
}

if

就像 for循環(huán)一樣,Go 的 if語句也不要求用 ()括號括起來剔宪,但是 {} 大括號表示作用域的內(nèi)容還是必須要有的拂铡。

func sqrt(x float64) string {
    if x<0 {
        return sqrt(-x) + "i"
    }
    return fmt.Sprint(math.Sqrt(x))
}

if的便捷語句

for語句一樣,if語句可以在條件之前執(zhí)行一個簡單的語句葱绒。由這個語句定義的變量的作用域僅在 if 范圍之內(nèi)感帅。

func pow(x,n,lim float64) float64 {
    if v := math.Pow(x,n); v < lim {
        return v
    }
    return lim 
}

if和else

if 的便捷語句定義的變量同樣可以在任何對應(yīng)的else塊中使用。(提示:兩個 pow 都在main 中調(diào)用 fmt.Println 前執(zhí)行完了)

func pow(x,n,lim float64) float64 {
    if v:math.Pow(x,n); v<lim{
        return v
    } else {
        fmt.Printf("%g >= %g\n",v,lim)
    }
    return lim
}

swith語句

switch除非以 fallthrough 語句結(jié)束地淀,否則分支會自動終止失球。

switch os: rumtime.GOOS ; os{
    case "darwin":
        fmt.Println("OS X")
    case "linux":
        fmt.Println("Linux")
    default:
        //freebsd , openbsd,
        //plan9,windows...
        fmt.Printf("%s.",os)
}

switch 的執(zhí)行順序

switch 的條件從上到下執(zhí)行,當匹配成功的時候停止帮毁。

switch i {
    case 0 :
    case f():
}
//當i==0時候不會調(diào)用 **f()**

today := time.Now().Weekday()
switch time.Saturday {
    case today + 0 :
        fmt.Println("Today.")
    case today + 1:
        fmt.Println("Tomorrow")
    case today + 2:
        fmt.Println("In two days")
    default:
        fmt.Println("Too far away")

}

沒有條件的swtich

沒有條件的switch 同 switch true一樣实苞。這一構(gòu)造使得可以用更清晰的形式來編寫長的if-then-else 鏈。

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.")
}

defer 語句

defer 語句會延遲函數(shù)的執(zhí)行烈疚,直到上層函數(shù)返回黔牵。延遲調(diào)用的參數(shù)會立即生成,但是在上層函數(shù)返回前函數(shù)都不會調(diào)用爷肝。

func main(){
    defer fmt.Println("world")
    
    fmt.Println("hello")
}

defer 棧
  延遲函數(shù)調(diào)用被壓入一個棧中猾浦。當函數(shù)后進先出的順序調(diào)用被延遲的函數(shù)調(diào)用。

fmt.Println("counting")

for i:= 0 ; i<10 ; i++{
    defer fmt.Println(i)
}
fmt.Println("done")

指針

go 具有指針灯抛。指針保存了變量的內(nèi)存地址金赦。

類型 *T 是執(zhí)行類型為 T 的指針,其零值是 nil对嚼。

var p *int 

&符號會生成一個指向其作用對象的指針素邪。

i := 42
p = &i

* 符號表示指針指向的底層的值。

fmt.Println(*p)   //通過指針p讀取i
*p = 21           //通過指針p設(shè)置i

這也就是通常所說的“間接引用”或“非直接引用”猪半。

與C不同兔朦,Go 沒有指針運算。

i磨确,j := 100 , 666

p := &i
fmt.Println(*p)    //通過p讀取I的值
*p = 777
fmt.Println(i)

p = &j
*p = *p / 37 
fmt.Println(j)

結(jié)構(gòu)體字段

結(jié)構(gòu)體字段使用點號來訪問(這點和C很像)

type Vertex struct {
    X int
    Y int
}

func main(){
    v:= Vertex(1,2)
    v.X = 4
    fmt.Println(v.X)
}

結(jié)構(gòu)指針

結(jié)構(gòu)體字段可以通過結(jié)構(gòu)體指針來訪問沽甥。

通過指針間接的訪問是透明的

type Vertex struct{
    X int
    Y int
}

func main(){
    v := Vertex{1,2}
    p := &v
    p.X = 1e9
    fmt.Println(v)
}

結(jié)構(gòu)體符文

結(jié)構(gòu)體符文表示通過結(jié)構(gòu)體字段的值作為列表來新分配一個結(jié)構(gòu)體。

使用 Name: 語法可以僅列部分字段乏奥。(字段名的順序無關(guān)摆舟。)

特殊的前綴 & 返回一個指向結(jié)構(gòu)體的指針。

type Vertex struct {
    X,Y int
}

var (
    v1 = Vertex{1,2}  //類型為 Vertex
    v2 = Vertex{X:1}  //Y:0 被省略
    v3 = Vertex{   }  //X:0 和 Y:0
    p = &Vertex{1,2}  //類型為 *Vertex
)

數(shù)組 (和C語言的數(shù)組概念類似)

類型 [n]T 是一個有 n 個類型為 T 的值的數(shù)組。

表達式

var a [10]int 

定義變量 a 是一個有十個整數(shù)的數(shù)組恨诱。

數(shù)組的長度是其類型的一部分媳瞪,因此數(shù)組不能改變大小。這看起來是一個制約照宝,但是Go提供一個更加便利的方式來使用數(shù)組蛇受。

切片(slice)

一個 slice 會指向一個序列的值,并且包含了長度信息厕鹃。

[]T 是一個元素類型為 T 的切片(slice)兢仰。

len(s) 返回 slice s 的長度。

func main(){
    s := []int{2,3,4,5,11,13}
    fmt.Println("s ==",s)
    for i:= 0 ; i < len(s) ; i++{
        fmt.Printf("s[%d] == %d\n",i,s[i])
    }
}

slice的切片
  切片slice 可以包含任意的類型剂碴,包括另一個 slice

func main(){
    //create a tic-tac-toe board
    game := [][]string{
        []string{"_","_","_"},
        []string{"_","_","_"},
        []string{"_","_","_"},
    }
    game[0][0] = "X"
    game[2][2] = "O"
    game[2][0] = "X"
    game[1][0] = "O"
    game[0][2] = "X"
    printBoard(game)
}

func printBoard(s [][]string){
    for i:=0 ; i < len(s); i++{
        fmt.Printf("%s\n",strings.Join(s[i]," "))  //TODO 不懂
    }
}

對slice切片

slice可以重新切片把将,創(chuàng)建新的 slice 值指向相同的數(shù)組。

表達式:

s[lo:hi]

表示從 lohi-1 的slice元素忆矛,含前端察蹲,不包含后端。因此:

s[lo:lo]

是空的催训,而

s[lo:lo+1]

具備一個元素洽议。

func main(){
    s := []int {2,3,5,7,11,13}
    fmt.Println("s == ",s)
    fmt.Println("s[1:4] ==",s[1:4])
    
    //省略下標從0 開始
    fmt.Println("s[:3] == ",s[:3])
    
    //省略上標到 len(s) 結(jié)束
    fmt.Println("s[4:] == ",s[4:])
}

構(gòu)造 slice
  slice 由函數(shù) make 創(chuàng)建。這會分配一個全是零值的數(shù)組并且返回一個 slice 指向這個數(shù)組:

a := make([]int,5) // len(a) = 5

為了指定容量瞳腌,可傳遞第三個參數(shù)到make :

b := make([]int,0,5) //len(b) = 0 , cap(b) = 5
b = b[:cap(b)]       //len(b) = 5 , cap(b) = 5
b = b[1:]            //len(b) = 4 , cap(b) = 4

以下為示例代碼:

func main(){
    a := make([]int,5)
    printSlice("a",a)
    
    b := make([]int,0,5)
    printSlice("b",b)
    
    c := b[:2]
    printSlice("c",c)
    
    d := c[2:5]
    printSlice("d",d)
}

func printSlice(s string, x []int){
    fmt.Printf("%s len=%d cap = %d %v\n",s,len(x),cap(x),x)
}

nil slice

slice 的零值是 nil

一個 nilslice 的長度和容量是 0

 var z []int
 fmt.Println(z,len(z),cap(z))
 if z == nil{
     fmt.Println("nil!")
 }

向slice添加元素

slice 的末尾添加元素是一種常見操作绞铃,因此 Go 提供了一個內(nèi)建函數(shù) append 。內(nèi)建函數(shù)的文檔對 append 有詳細介紹嫂侍。

func append(s []T, vs ...T) []T

append 的第一個參數(shù)是 s 是一個元素類型為 Tslice 儿捧,其余類型為 T 的值將會附加到該 slice 的末尾。

append 的結(jié)果是一個包含原 **slice** 所有元素加上新添加的元素 **slice**挑宠。

如果 s 的底層數(shù)組太小菲盾,而不能容納所有值的時候,會分配一個更大的數(shù)組各淀。返回 slice 會指向這個新分配的數(shù)組懒鉴。

func main(){
    var a []int
    printSlice("a",a)

    a = append(a,0)
    printSlice("a",a)

    a = append(a,1)
    printSlice("a",a)

    a = append(a,2,3,4)
    printSlice("a",a)
}

func printSlice(s string, x []int){
    fmt.Printf("%s len=%d cap=%d %v\n", s , len(x) , cap(x) , x)
}

范圍(range)

for 循環(huán)的 range 格式可以對 slice 或者 map 進行迭代循環(huán)。

當使用 for 循環(huán)遍歷一個 slice 時候碎浇,每次迭代 range 將返回兩個值临谱。第一個是當前的下標(序號),第二個是該下標所對應(yīng)元素的一個拷貝奴璃。

var pow = []int{1,2,4,8,16,32,64,128}

func main(){
    for i,v:= range pow{
        fmt.Printf("2 ** %d = %d \n",i,v)
    }
}

通過賦值給 _ 來忽略序號和值悉默。

如果只需要索引值,去掉 “苟穆,value” 的部分就可以了抄课。

func main(){
    pow := make([] int,10)
    for i := range pow{
        pow[i] = 1 << uint(i)
    }
    
    for _,value := range pow{
        fmt.Printf("%d\n",value)
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唱星,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子跟磨,更是在濱河造成了極大的恐慌间聊,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件抵拘,死亡現(xiàn)場離奇詭異哎榴,居然都是意外死亡,警方通過查閱死者的電腦和手機仑濒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門叹话,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偷遗,“玉大人墩瞳,你說我怎么就攤上這事∈贤悖” “怎么了喉酌?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泵喘。 經(jīng)常有香客問我泪电,道長,這世上最難降的妖魔是什么纪铺? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任相速,我火速辦了婚禮,結(jié)果婚禮上鲜锚,老公的妹妹穿的比我還像新娘突诬。我一直安慰自己,他們只是感情好芜繁,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布旺隙。 她就那樣靜靜地躺著,像睡著了一般骏令。 火紅的嫁衣襯著肌膚如雪蔬捷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天榔袋,我揣著相機與錄音周拐,去河邊找鬼。 笑死凰兑,一個胖子當著我的面吹牛妥粟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播聪黎,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼罕容,長吁一口氣:“原來是場噩夢啊……” “哼备恤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起锦秒,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤露泊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后旅择,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惭笑,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年生真,在試婚紗的時候發(fā)現(xiàn)自己被綠了沉噩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡柱蟀,死狀恐怖川蒙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情长已,我是刑警寧澤畜眨,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站术瓮,受9級特大地震影響康聂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜胞四,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一恬汁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辜伟,春花似錦氓侧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至烘豌,卻和暖如春载庭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背廊佩。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工囚聚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人标锄。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓顽铸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親料皇。 傳聞我的和親對象是個殘疾皇子谓松,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 出處---Go編程語言 歡迎來到 Go 編程語言指南星压。本指南涵蓋了該語言的大部分重要特性 Go 語言的交互式簡介,...
    Tuberose閱讀 18,399評論 1 46
  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型鬼譬。 運用指針編程是C語言最主要的風(fēng)格之一娜膘。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,424評論 3 44
  • Hello World這是開發(fā)的一個開發(fā)魔咒优质,幾乎所有人都是從這開始的竣贪,今天我也從魔咒開始先打印一份Hello W...
    cocoaAhda閱讀 1,429評論 0 3
  • 費思屹同學(xué)播報: 大家好,我是費思屹巩螃,今天由我來播報演怎,我播報的內(nèi)容是P61《母親的冬天》以及P64《人生是不能輕易...
    簡約語文閱讀 629評論 0 1
  • 今天凌晨做了一個夢爷耀,夢見我騎著自行車,悠閑的在我現(xiàn)在住的地方旁邊的一所大學(xué)校園里騎著淑际,忽然意識到畏纲,離開校園...
    Richard1015閱讀 318評論 0 2