1. 程式人生 > >go語言核心36講要點概括(1-5)

go語言核心36講要點概括(1-5)

01 | 工作區和GOPATH

gopath指的是工作空間(包括原始碼,可以有多個)

構建使用命令go build,安裝使用命令go install。構建和安裝程式碼包的時候都會執行編譯、打包等操作,並且這些操作生成的任何檔案都會先被儲存到某個臨時的目錄中。

go install命令安裝的是庫原始碼檔案時會產生歸檔檔案,結果檔案會被搬運到它所在工作區的 pkg 目錄下的某個子目錄

go install命令安裝的是命令原始碼檔案,那麼結果檔案會被搬運到它所在工作區的bin 目錄中,或者環境變數GOBIN指向的目錄中。

go build可以沒有命令原始碼檔案,構建命令原始碼檔案時候,生成的可執行檔案檔名會與檔案所在目錄的名字一樣

在執行go build命令的時候,預設不會編譯目的碼包所依賴的那些程式碼包。當然,如果被依賴的程式碼包的歸檔檔案不存在,

或者原始碼檔案有了變化,那它還是會被編譯。

當有多個檔案時,go build必須一起構建

下載包命令 : go get

go get 雖然簡單粗暴,但是缺點是不能進行版本控制

思考題

Go 語言在多個工作區中查詢依賴包的時候是以怎樣的順序進行的?

如果在多個工作區中都存在匯入路徑相同的程式碼包會產生衝突嗎?

02 | 命令原始碼檔案

1.原始碼檔案分為三種:命令原始碼檔案(有main方法)、庫原始碼檔案和測試原始碼檔案

2.編寫命令原始碼檔案的關鍵包: flag。

程式碼

package main

import (
	"fmt"
	"flag"
)

var name  string

func init()  {
	//函式flag.StringVar接受 4 個引數。第 1 個是接收命令引數值的地址,第二個是命令引數的名稱
	//第三個是當命令引數沒值時候的預設值   第四個是該命令引數的簡單說明
	flag.StringVar(&name,"name","everyone","The greeting object.")
	//var name = flag.String("name", "everyone", "The greeting object.")
}

func main()  {
	//解析命令引數,並把它們的值賦給相應的變數。
	flag.Parse()
	fmt.Printf("hello,%s\n",name)
}

執行結果

用help檢視引數說明

圖片第二行的路徑是命令構建上述命令原始碼檔案時臨時生成的可執行檔案的完整路徑

思考題

預設情況下,我們可以讓命令原始碼檔案接受哪些型別的引數值?

我們可以把自定義的資料型別作為引數值的型別嗎?如果可以,怎樣做?

03 | 庫原始碼檔案

在同一目錄下的原始碼檔案  都必須宣告屬於同一個包(比如你在一個資料夾下建立了一個命令原始碼檔案,該資料夾下其他的所有go檔案都必須宣告為main包)

原始碼檔案宣告的包名可以與其所在目錄名稱不同,但是同一目錄下的原始碼檔案 必須宣告同樣的包名

可以看到,當引用別的目錄的原始碼檔案時,匯入的包路徑為資料夾的名字(既other,該路徑是相對於src的路徑),而呼叫的時候卻是通過包名來呼叫(other1)

注意

當需要執行上面程式碼時,只需要go run main.go

如果上圖的main方法裡呼叫的是yasuo包裡的Hello()方法時,則需要go run 兩個檔案,如下圖,否則就會報錯 

undefined: Hello

或者是>go build go36/day3/yasuo(src的相對路徑)

原因是因為前面是引入了程式碼包,所有run的時候,可以通過路徑找到對應的檔案,然後編譯構建執行,後面報錯是因為找不到庫原始碼檔案,因為沒指定(我猜的)

模組級私有internal的使用姿勢

思考題

如果你需要匯入兩個程式碼包,而這兩個程式碼包的匯入路徑的最後一級是相同的,比如:dep/lib/flag和flag,那麼會產生衝突嗎?

如果會產生衝突,那麼怎樣解決這種衝突,有幾種方式?

1.import後路徑最後一級相同,不一定會衝突。
分為兩種情況:
a.如果資料夾下檔案宣告的包名相同,則肯定衝突,會報錯redeclared。
b.如果資料夾下檔案宣告的包名不同,也不會衝突。
 

2.如果衝突,我能想到的解決方式:
a.給包設定別名,呼叫的時候來區分開不同的package,比如:import(b "bbbb")

b.匯入的點操作,import(. "bbbb")。這樣就可以直接呼叫bbbb下面的函式而不用再bbbb.funcname的方式呼叫。

c.如果只是想引入某包並沒有在程式碼中實際呼叫則可以這麼處理來避免衝突:import(_ "bbbb")

d.採取不同的包名宣告

04 | 程式實體的那些事兒(上)

var name = 1

name := 1(短變數宣告)

短變數宣告只能在函式體內部使用短變數宣告。

05 | 程式實體的那些事兒(中)

如果我們把程式碼包匯入語句寫成import . XXX的形式(注意有個.),那麼就會讓這個“XXX”包中公開的程式實體被當前原始碼檔案中的程式碼,視為當前程式碼包中的程式實體

變數重宣告是對同一個變數的多次宣告,這裡的變數只有一個。而可重名變數中涉及的變數肯定是有多個的。

不論對變數重宣告多少次,其型別必須始終一致,具體遵從它第一次被宣告時給定的型別。而可重名變數之間不存在類似的限制,它們的型別可以是任意的。

如果可重名變數所在的程式碼塊之間存在直接或間接的巢狀關係,那麼它們之間一定會存在“遮蔽”的現象。但是這種現象絕對不會在變數重宣告的場景下出現。