go語言學(xué)習(xí)(日更)

前段時間準(zhǔn)備面試国拇,學(xué)院里面考試以及家里面有些事情,還有我懶,耽擱了怀各。
現(xiàn)在一切就緒,可以開新坑了~嘿嘿嘿
大部分資料都源自于互聯(lián)網(wǎng) 但是大部分都是自己手打(侵刪)

首先確保各位的GOPATH的版本大于等于1.8 保證環(huán)境的一致性
本人也是初學(xué)go語言术浪,如果有錯誤希望各位指正瓢对。

基本程序

首先我們先寫一個最最最簡單的hello word吧

package main //包,表明代碼所在的模塊(包)
import "fmt" //引?代碼依賴
//功能實現(xiàn)
func main() {
 fmt.Println("Hello World!")
}

以上胰苏,我們很容易看出(如果你有其他語言的基礎(chǔ)的話)程序的入口
1.一定是在main包下:也就是package main //包硕蛹,表明代碼所在的模塊(包)
2.必須要是在main方法:func main()

  1. 其實文件名不一定是main.go

此時肯定會有人問,既然是函數(shù)肯定會有返回值啦~
比如c語言默認(rèn)會追加一個return

對硕并,有道理但是

Go 中 main 函數(shù)不?持任何返回值
如果你需要有返回狀態(tài)法焰,你可以通過
通過 os.Exit 來返回狀態(tài)

常量和變量

變量

接觸常量和變量的時候我們先規(guī)定以后編寫代碼的時候用test程序

也就是

源碼?件以 _test 結(jié)尾:xxx_test.go
測試?法名以 Test 開頭:func TestXXX(t *testing.T) {…}
這樣就不用重復(fù)開很多項目了(真棒)
和java的junit單元測試一樣好用,還能打印日志

先寫一個斐波那契數(shù)列吧

func TestFibList(t *testing.T) {
    // var a int = 1
    // var b int = 1
    // var (
    //  a int = 1
    //  b     = 1
    // )
    a := 1
    // a := 1
    b := 1
    t.Log(a)
    for i := 0; i < 5; i++ {
        t.Log(" ", b)
        tmp := a
        a = b
        b = tmp + a
    }

}

變量有多種賦值方式(在上面)
? 賦值可以進(jìn)??動類型推斷
? 在?個賦值語句中可以對多個變量進(jìn)?同時賦值

注意 a := 1 只能用于局部變量倔毙,不能作用于全局變量

常量

const: 關(guān)鍵字 使得被起修飾的變量可讀不可寫 保證其狀態(tài)
同時:iota (偷懶的寫法 如果不愿意一直+1 這個可以替代) 我暫時還沒用它寫過復(fù)雜的程序

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

bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr(正數(shù))
byte // alias for uint8
rune // alias for int32,represents a Unicode code point
float32 float64
complex64 complex128

類型轉(zhuǎn)化

  1. Go 語?不允許隱式類型轉(zhuǎn)換
  2. 別名和原有類型也不能進(jìn)?隱式類型轉(zhuǎn)換
func TestImplicit(t *testing.T) {
    var a int32 = 1
    var b int64
    b = int64(a)
    var c MyInt
    c = MyInt(b)
    t.Log(a, b, c)
}

以上是顯示類型轉(zhuǎn)換 如果直接b=a就會報錯
所以編程的過程中需要小心

指針類型

  1. 不?持指針運算(所以別想著指針操作下一個數(shù)組單位)
  2. string 是值類型埃仪,其默認(rèn)的初始化值為空字符串,?不是 nil
func TestPoint(t *testing.T) {
    a := 1
    aPtr := &a
    //aPtr = aPtr + 1
    t.Log(a, aPtr)
    t.Logf("%T %T", a, aPtr)
}

運算符

就不多提 有編程經(jīng)驗的直接跳過

不過這塊著重一點就是 Go 語?沒有前置的 ++陕赃,- -
(作用的話卵蛉,我猜應(yīng)該是增加代碼的可讀性吧)

循環(huán)

也不多提
Go 語?僅?持循環(huán)關(guān)鍵字 for

n := 0
for n < 5 {
 n++
 fmt.Println(n)
}

怎么感覺好像更難讀了1?不過沒事,習(xí)慣就好了

switch條件

  1. 條件表達(dá)式不限制為常量或者整數(shù)么库;
  2. 單個 case 中傻丝,可以出現(xiàn)多個結(jié)果選項, 使?逗號分隔;
  3. 與 C 語?等規(guī)則相反诉儒,Go 語?不需要?break來明確退出?個 case葡缰;如果需要執(zhí)行下一個case的話 可以加fallthrough關(guān)鍵字
  4. 可以不設(shè)定 switch 之后的條件表達(dá)式,在此種情況下忱反,整個 switch 結(jié)
    構(gòu)與多個 if…else… 的邏輯作?等同

數(shù)組和切片

這個很重要 以后有機(jī)會開個新坑形容一下底層原理

數(shù)組的聲明

var a [3]int //聲明并初始化為默認(rèn)零值
a[0] = 1

b := [3]int{1, 2, 3} //聲明同時初始化

元素的遍歷

func TestTravelArray(t *testing.T) {
 a := [...]int{1, 2, 3, 4, 5} //不指定元素個數(shù)
 for idx/*索引*/, elem/*元素*/ := range a {
 fmt.Println(idx, elem)
 }
//當(dāng)然 你要是不想要ind(索引的話)可以變?yōu)開 不使用它就行
}

數(shù)組的截取

a[開始索引(包含), 結(jié)束索引(不包含)]
(簡單來記就是左閉右開)

a := [...]int{1, 2, 3, 4, 5}
a[1:2] //2
a[1:3] //2,3
a[1:len(a)] //2,3,4,5
a[1:] //2,3,4,5
a[:3] //1,2,3

![X~VMAEVUTITZ3TFJ_O%2)6.png

這個挺復(fù)雜的后面詳細(xì)講泛释,初學(xué)者會使用就行

切片的聲明

var s0 []int
s0 = append(s0, 1)
s := []int{}
s1 := []int{1, 2, 3}
s2 := make([]int, 2, 4) 
 /*[]type, len, cap
 其中l(wèi)en個元素會被初始化為默認(rèn)零值,未初始化元素不可以訪問
 */

切?共享存儲結(jié)構(gòu)

image.png

數(shù)組和切片的區(qū)別

  1. 容量是否可伸縮
  2. 是否可以進(jìn)??較

Map基礎(chǔ)

本節(jié)也很重要 不過作為初學(xué)者只要掌握使用即可

Map 聲明

m := map[string]int{"one": 1, "two": 2, "three": 3}
m1 := map[string]int{}
m1["one"] = 1
m2 := make(map[string]int, 10 /*Initial Capacity*/)

Map還有一個很有意思的點温算,就是假如我設(shè)置一個key但是并未設(shè)置value 那么這個value設(shè)置為0值
此時 好處當(dāng)然就是防止空指針異常呀
但是壞處也有怜校,就是我這么知道這個key的value是真的為空還是就為0?
以下代碼中 ok 為true存在 否則不存在

func TestAccessNotExistingKey(t *testing.T) {
    m1 := map[int]int{}
    t.Log(m1[1])
    m1[2] = 1
    t.Log(m1[2])
    m1[1] = 2
    if v, ok := m1[3]; ok {
        t.Logf("Key 3's value is %d", v)
    } else {
        t.Log("key 3 is not existing.")
    }
}

遍歷map

func TestTravelMap(t *testing.T) {
    m1 := map[int]int{1: 1, 4: 4, 3: 9}
    for k, v := range m1 {
        t.Log(k, v)
    }
}

Map的擴(kuò)展

Map 與??模式
? Map 的 value 可以是?個?法
? 與 Go 的 Dock type 接??式?起米者,可以?便的實現(xiàn)單??法對象的??模式

實現(xiàn) Set
Go 的內(nèi)置集合中沒有 Set 實現(xiàn)韭畸, 可以 map[type]bool

  1. 元素的唯?性
  2. 基本操作
  1. 添加元素
  2. 判斷元素是否存在
  3. 刪除元素
  4. 元素個數(shù)
func TestMapWithFunValue(t *testing.T) {
    m := map[int]func(op int) int{}
    m[1] = func(op int) int { return op }
    m[2] = func(op int) int { return op * op }
    m[3] = func(op int) int { return op * op * op }
    t.Log(m[1](2), m[2](2), m[3](2))
}

用Map實現(xiàn)set

func TestMapForSet(t *testing.T) {
    mySet := map[int]bool{}
    mySet[1] = true
    n := 3
    if mySet[n] {
        t.Logf("%d is existing", n)
    } else {
        t.Logf("%d is not existing", n)
    }
    mySet[3] = true
    t.Log(len(mySet))
    delete(mySet, 1)
    n = 1
    if mySet[n] {
        t.Logf("%d is existing", n)
    } else {
        t.Logf("%d is not existing", n)
    }
}

string

  1. string 是數(shù)據(jù)類型宇智,不是引?或指針類型
  2. string 是只讀的 byte slice蔓搞,len 函數(shù)可以它所包含的 byte 數(shù)
  3. string 的 byte 數(shù)組可以存放任何數(shù)據(jù)

函數(shù)

  1. 可以有多個返回值
  2. 所有參數(shù)都是值傳遞:slice,map随橘,channel 會有傳引?的錯覺
  3. 函數(shù)可以作為變量的值
  4. 函數(shù)可以作為參數(shù)和返回值
func returnMultiValues() (int, int) {
    return rand.Intn(10), rand.Intn(20)
}

func timeSpent(inner func(op int) int) func(op int) int {
    return func(n int) int {
        start := time.Now()
        ret := inner(n)
        fmt.Println("time spent:", time.Since(start).Seconds())
        return ret
    }
}

func slowFun(op int) int {
    time.Sleep(time.Second * 1)
    return op
}

func TestFn(t *testing.T) {
    a, _ := returnMultiValues()
    t.Log(a)
    tsSF := timeSpent(slowFun)
    t.Log(tsSF(10))
}

可變參數(shù)

func sum(ops ...int) int {
 s := 0
 for _, op := range ops {
 s += op
 }
 return s
}

最終拿到的就是所有參數(shù)之和

defer 函數(shù)

func TestDefer(t *testing.T) {
defer func() {
t.Log("Clear resources")
}()
t.Log("Started")
panic("Fatal error”) //defer仍會執(zhí)?
}

?向?qū)ο缶幊?/h1>

結(jié)構(gòu)體定義

type Employee struct {
 Id string
 Name string
 Age int
}

實例創(chuàng)建及初始化

e := Employee{"0", "Bob", 20}
e1 := Employee{Name: "Mike", Age: 30}
e2 := new(Employee) //注意這?返回的引?/指針喂分,相當(dāng)于 e := &Employee{}
e2.Id = “2" //與其他主要編程語?的差異:通過實例的指針訪問成員不需要使?->
e2.Age = 22
e2.Name = “Rose"


//第?種定義?式在實例對應(yīng)?法被調(diào)?時,實例的成員會進(jìn)?值復(fù)制
func (e Employee) String() string {
return fmt.Sprintf("ID:%s-Name:%s-Age:%d", e.Id, e.Name, e.Age)
} 
//通常情況下為了避免內(nèi)存拷?我們使?第?種定義?式
func (e *Employee) String() string {
return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)
}

定義交互協(xié)議

接?與依賴

{ISI6UY47_0~0P(D07D%}K3.png

用java實現(xiàn)

Programmer.java
public interface Programmer {
String WriteCodes() ;
}

GoProgrammer.java
public class GoProgrammer implements Programmer {
@Override
public String WriteCodes() {
return "fmt.Println(\"Hello World\")";
} }

Task.java
public class Task{
public static void main(String[] args) {
Programmer prog = new GoProgrammer();
String codes = prog.WriteCodes();
System.out.println(codes);
} }

定義 實現(xiàn) 調(diào)用接口的過程

但是在go語言中机蔗,我們可以使用鴨子類型

接?定義
type Programmer interface {
    WriteHelloWorld() 
}

 接?實現(xiàn)
type GoProgrammer struct {
}

func (p *GoProgrammer) WriteHelloWorld() Code {
return "fmt.Println(\"Hello World!\")"
}

我們發(fā)現(xiàn)這個是通過組合的方式完成接口的實現(xiàn)的

Go 接?

與其他主要編程語?的差異

  1. 接?為??侵性蒲祈,實現(xiàn)不依賴于借?定義
  2. 所以接?的定義可以包含在接?使?者包內(nèi)

接?變量

K9J5N{@QJ4TTP%G{WGNIZ@D.png

自定義類型

就自定義的 比如struct 然后就能當(dāng)做一個特殊類型使用(這個有c語言基礎(chǔ)能理解)

擴(kuò)展與復(fù)?

復(fù)合
與其他主要編程語?的差異
Go 不?持繼承甘萧,但可以通過復(fù)合的?式來復(fù)?


type Pet struct {
}

func (p *Pet) Speak() {
    fmt.Println("...PET")
}

func (p *Pet) SpeakTo(host string) {
    p.Speak()
    fmt.Println(" ", host)
}

type Dog struct {
    Pet
}

func (d *Dog) Speak() {
    fmt.Println("Wang!")
}

func TestDog(t *testing.T) {
    dog := new(Dog)

    dog.SpeakTo("Chao")
}

可以通過組合對程序進(jìn)行繼承

匿名類型嵌?
與其他主要編程語?的差異
它不是繼承,如果我們把“內(nèi)部 struct ”看作?類梆掸,把“外部 struct” 看作?類扬卷,
會發(fā)現(xiàn)如下問題:

  1. 不?持?類替換
  2. ?類并不是真正繼承了?類的?法
    ? ?類的定義的?法?法訪問?類的數(shù)據(jù)和?法

多態(tài)

BP@5KY2PYF(XGX(4@Q1AP71.png

空接?與斷?

  1. 空接?可以表示任何類型
  2. 通過斷?來將空接?轉(zhuǎn)換為制定類型
    v, ok := p.(int) //ok=true 時為轉(zhuǎn)換成功

Go 接?最佳實踐
傾向于使??的接?定義,很多接
?只包含?個?法

type Reader interface {
 Read(p []byte) (n int, err error)
}
type Writer interface {
 Write(p []byte) (n int, err error)
}

較?的接?定義酸钦,可以由多個?接
?定義組合?成

type ReadWriter interface {
 Reader
 Writer
}

只依賴于必要功能的最?接?

func StoreData(reader Reader) error {
 …
}

Go 的錯誤機(jī)制

  1. 沒有異常機(jī)制
  2. error 類型實現(xiàn)了 error 接?
type error interface {
 Error() string
}
  1. 可以通過 errors.New 來快速創(chuàng)建錯誤實例
errors.New("n must be in the range [0,100]")

panic
? panic ?于不可以恢復(fù)的錯誤
? panic 退出前會執(zhí)? defer 指定的內(nèi)容

panic vs. os.Exit
? os.Exit 退出時不會調(diào)? defer 指定的函數(shù)
? os.Exit 退出時不輸出當(dāng)前調(diào)?棧信息

recover

Java

try{
 …
}catch(Throwable t){
}

C++

try{
 …
}catch(…){
}

recover

defer func() {
if err := recover(); err != nil {
 //恢復(fù)錯誤
         }
}()

init ?法
? 在 main 被執(zhí)?前怪得,所有依賴的 package 的 init ?法都會被執(zhí)?
? 不同包的 init 函數(shù)按照包導(dǎo)?的依賴關(guān)系決定執(zhí)?順序
? 每個包可以有多個 init 函數(shù)
? 包的每個源?件也可以有多個 init 函數(shù),這點?較特殊

Thead vs. Groutine

  1. 創(chuàng)建時默認(rèn)的 stack 的??
    ? JDK5 以后 Java Thread stack 默認(rèn)為1M
    ? Groutine 的 Stack 初始化??為2K
  2. 和 KSE (Kernel Space Entity) 的對應(yīng)關(guān)系
    ? Java Thread 是 1:1
    ? Groutine 是 M:N

![UXJQWHW]2OSZG67]IKT~W00.png](https://upload-images.jianshu.io/upload_images/24046024-5f98801ae75eeb49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末卑硫,一起剝皮案震驚了整個濱河市徒恋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌欢伏,老刑警劉巖入挣,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異硝拧,居然都是意外死亡径筏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門障陶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匠璧,“玉大人,你說我怎么就攤上這事咸这∫幕校” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵媳维,是天一觀的道長酿雪。 經(jīng)常有香客問我,道長侄刽,這世上最難降的妖魔是什么指黎? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮州丹,結(jié)果婚禮上醋安,老公的妹妹穿的比我還像新娘。我一直安慰自己墓毒,他們只是感情好吓揪,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著所计,像睡著了一般柠辞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上主胧,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天叭首,我揣著相機(jī)與錄音习勤,去河邊找鬼。 笑死焙格,一個胖子當(dāng)著我的面吹牛图毕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播眷唉,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼吴旋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了厢破?” 一聲冷哼從身側(cè)響起荣瑟,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎摩泪,沒想到半個月后笆焰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡见坑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年嚷掠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荞驴。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡不皆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熊楼,到底是詐尸還是另有隱情霹娄,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布鲫骗,位于F島的核電站犬耻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏执泰。R本人自食惡果不足惜炼杖,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一笋熬、第九天 我趴在偏房一處隱蔽的房頂上張望褐荷。 院中可真熱鬧罩引,春花似錦、人聲如沸排苍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纪岁。三九已至凑队,卻和暖如春则果,著一層夾襖步出監(jiān)牢的瞬間幔翰,已是汗流浹背漩氨。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留遗增,地道東北人叫惊。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像做修,于是被迫代替她去往敵國和親霍狰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

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