您好,登錄后才能下訂單哦!
隨便學(xué)學(xué),平時(shí)用的都是WIndows10的操作系統(tǒng),就在這下面搞了。
下載go安裝程序,下載地址:https://golang.org/dl/ (被墻了,打不開)
墻內(nèi)下載地址http://www.golangtc.com/download
我下的是這個(gè):go1.9.2.windows-amd64.msi
安裝就下一步就好了,裝完之后驗(yàn)證一下。默認(rèn)已經(jīng)把Go的路徑加到環(huán)境變量中去了,所以可以直接在cmd中輸入go命令執(zhí)行:
裝完之后,我裝到了D:\Go\,已經(jīng)幫我們添加好了2個(gè)環(huán)境變量:
GOPATH也是要的,設(shè)置工作區(qū)路徑,不過如果沒有設(shè)置的話,有一個(gè)默認(rèn)位置(差不多就是系統(tǒng)的家目錄)。執(zhí)行幫助命令 go help gopath
,我這截了一段說明:
If the environment variable is unset, GOPATH defaults
to a subdirectory named "go" in the user's home directory
($HOME/go on Unix, %USERPROFILE%\go on Windows),
unless that directory holds a Go distribution.
Run "go env GOPATH" to see the current GOPATH.
暫時(shí)不設(shè)置也沒影響,反正也有默認(rèn)的,后面寫 Hellow World 的時(shí)候再看設(shè)置在哪個(gè)目錄
開發(fā)工具先沒有裝,不過這里先記一下工具的名稱:
Visual Studio Code (簡(jiǎn)稱 VS Code / VSC) 是一款免費(fèi)開源的現(xiàn)代化輕量級(jí)代碼編輯器,支持幾乎所有主流的開發(fā)語言的語法高亮、智能代碼補(bǔ)全、自定義熱鍵、括號(hào)匹配、代碼片段、代碼對(duì)比 Diff、GIT 等特性,支持插件擴(kuò)展,并針對(duì)網(wǎng)頁(yè)開發(fā)和云端應(yīng)用開發(fā)做了優(yōu)化。軟件跨平臺(tái)支持 Win、Mac 以及 Linux。
這是一個(gè)通用的代碼編輯器,裝完之后要再裝一下go的擴(kuò)展:
Delve是一個(gè)非常棒的golang調(diào)試工具,支持多種調(diào)試方式,直接運(yùn)行調(diào)試,或者attach到一個(gè)正在運(yùn)行中的golang程序,進(jìn)行調(diào)試。
安裝Delve非常簡(jiǎn)單,直接運(yùn)行 go get 即可:
go get -u github.com/derekparker/delve/cmd/dlv
先記一下,我并沒有裝
在第一次寫代碼前,還要先把go的工作區(qū)設(shè)置好。
工作區(qū)是存放go源碼文件的目錄。一般情況,Go源碼文件都需要存放到工作區(qū)中,不過命令源碼文檔不是必須的。
每個(gè)工作區(qū)的目錄結(jié)構(gòu)都類似,有3個(gè)文件夾:
找一個(gè)合適的位置,作為工作區(qū)。比如:E:\Go。這時(shí)就可以去把GOPATH環(huán)境變量設(shè)置為 “E:\Go” 。
按上面說的,還要工作區(qū)中還要?jiǎng)?chuàng)建3個(gè)文件夾,暫時(shí)只需要src,另外兩個(gè)暫時(shí)不用。
到這里需要一些儀式感,就是寫一個(gè) Hellow World 。在src目錄下創(chuàng)建文件 “hellow.go” 。如果用了VS Code,會(huì)提示你裝一些擴(kuò)展,點(diǎn)下Install All,這樣會(huì)自動(dòng)把一些go的插件給裝好。
下面是程序的源碼:
package main
import(
"fmt"
)
func main() {
fmt.Println("Hello World")
}
第一部分,聲明這是一個(gè)包??蓤?zhí)行文件的包名必須是“main”。
第二部分,導(dǎo)入包。所有的庫(kù),包括自己的庫(kù),用之前都需要導(dǎo)入。fmt是包名,里面有一個(gè)方法可以向終端打印信息。
第三部分,定義了一個(gè)函數(shù)。必須要定義一個(gè)main函數(shù),這是個(gè)入口函數(shù)。
最后在cmd命令行里運(yùn)行一下:
go run hello.go
這次寫一個(gè)有參數(shù)有返回值的函數(shù):
package main
import(
"fmt"
)
func add(a int, b int) int {
var sum int
sum = a + b
return sum
}
func main(){
var c int
c = add(11, 22)
fmt.Println("11 + 22 =", c)
}
go是一個(gè)強(qiáng)類型語言,所有變量都要設(shè)置類型。
add函數(shù),寫參數(shù)的時(shí)候,參數(shù)后面要用類型。并且由于add函數(shù)有返回值,返回值的類型也要在函數(shù)名后面定義好。
聲明變量用var,后面是變量名,在后面是變量的類型。
最后如果你的變量定義之后,沒有被應(yīng)用,也是會(huì)報(bào)錯(cuò)的。這樣強(qiáng)制你去掉冗余的代碼,這個(gè)變量既然沒有用到,自然就不需要出現(xiàn),比如把最后一句fmt.Println(c)去掉或者換成打印一個(gè)固定的字符串就會(huì)報(bào)錯(cuò)。
先寫一個(gè)程序goroute_print.go,很簡(jiǎn)單,就是傳入?yún)?shù)稍微計(jì)算一下,然后打印結(jié)果:
package main
import (
"fmt"
)
func goroute_print(a int) {
b := a + 10000
fmt.Println(b)
}
這里用了 “:=” ,是聲明并賦值,并且系統(tǒng)自動(dòng)推斷類型,不需要var關(guān)鍵字。
然后再寫一個(gè)程序goroute_for.go,里面是一個(gè)for循環(huán),起若干個(gè)線程執(zhí)行:
package main
import(
"time"
)
func main(){
for i := 0; i < 1000; i++ {
go goroute_print(i)
}
// sleep1秒,保證上面的子線程運(yùn)行結(jié)束
time.Sleep(time.Second * 5)
}
在這個(gè)主程序要里調(diào)用另外一個(gè)文件里的程序。不過這2個(gè)文件都是同一個(gè)包,main包,開頭package聲明的。這里在前面加上了go調(diào)用,就是起了一個(gè)goroute。(不加go調(diào)用,就是在主線程里調(diào)用函數(shù),如果調(diào)用前加上go,就是起了一個(gè)子線程調(diào)用這個(gè)函數(shù))
主線程必須要等待子線程運(yùn)行結(jié)束才能退出,否則主線程一旦結(jié)束,其他子線程也就沒有了。這里簡(jiǎn)單粗暴的先用sleep來進(jìn)行等待。導(dǎo)入了一個(gè)time包。參數(shù) time.Second 就是1秒,如果不是等1秒而是幾秒的話,就乘以幾。
這里還有注釋,注釋的用法js一樣。單行注釋以 // 開頭,多行注釋以 /* 開始,以 */ 結(jié)尾。
執(zhí)行的話在cmd命令行執(zhí)行下面的命令:
go run goroute_for.go goroute_print.go
這個(gè)例子分在兩個(gè)文件里了,所以run后面把兩個(gè)文件都要寫上。順序是無所謂的。
這里用了make()函數(shù),是用來分配內(nèi)存的。第一個(gè)參數(shù) chan int
,表示要?jiǎng)?chuàng)建的是chan(管道),類型是int:
package main
import(
"fmt"
)
func main(){
pipe := make(chan int, 3) // 創(chuàng)建一個(gè)管道,存的數(shù)據(jù)類型是int,容量是3
pipe <- 11 // 往管道里存一個(gè)數(shù)
fmt.Println(11, len(pipe)) // 打印長(zhǎng)度
pipe <- 22
fmt.Println(22, len(pipe))
var t1 int
t1 =<- pipe // 從管道里取出一個(gè)數(shù),賦值給t1
fmt.Println(t1, len(pipe))
t1 =<- pipe
fmt.Println(t1, len(pipe))
}
似乎就是個(gè)隊(duì)列,先進(jìn)先出,默認(rèn)滿了也會(huì)阻塞。之所以叫管道不叫隊(duì)列,可能是它能支持多個(gè)goroute之間通過channel(管道)進(jìn)行通信。暫時(shí)不需要這么深入。
有兩種方式可以實(shí)現(xiàn)。把管道定義為全局變量,或者把管道作為函數(shù)的參數(shù)傳遞。代碼中使用全局變量不是好的做法,所以推薦用傳參的方法。不過兩種實(shí)現(xiàn)方法都看一下。
全局變量的代碼示例:
package main
import(
"fmt"
)
var pipe chan int // 在全局聲明pipe變量,下面兩個(gè)方法里都會(huì)用到
func add(a int, b int){
sum := a + b
pipe <- sum
}
func main(){
pipe = make(chan int, 1)
go add(1, 2)
sum :=<- pipe
fmt.Println("sum =", sum)
}
傳遞參數(shù)的代碼示例:
package main
import(
"fmt"
)
func add(a int, b int, c chan int){
sum := a + b
c <- sum
}
func main(){
var pipe chan int // 在main函數(shù)里聲明pipe
pipe = make(chan int, 1)
go add(3, 4, pipe)
sum :=<- pipe
fmt.Println("sum =", sum)
}
package main
import(
"fmt"
)
func calc(a int, b int)(int, int){
c1 := a + b
c2 := (a + b)/2
return c1, c2
}
func main(){
sum , avg := calc(100, 200)
fmt.Println("sum =", sum, "avg =", avg)
}
如果多返回值里只想取其中部分的值,可以把剩下的值傳給占位符(“_”):
package main
import(
"fmt"
)
func calc(a int, b int)(int, int){
c1 := a + b
c2 := (a + b)/2
return c1, c2
}
func main(){
sum , _ := calc(100, 200)
fmt.Println("sum =", sum)
fmt.Println(_) // 打印下劃線會(huì)報(bào)錯(cuò)
}
嘗試打印下劃線的報(bào)錯(cuò)信息如下:
>go run calc.go
# command-line-arguments
.\calc.go:17:16: cannot use _ as value
go默認(rèn)提供一個(gè)代碼格式化命令 gofmt
,會(huì)按照Go語言代碼規(guī)范格式化文件中的代碼。把之前的hello.go的代碼搞亂一點(diǎn),簡(jiǎn)單一點(diǎn)就改下縮進(jìn)好了,然后運(yùn)行下面的命令:
gofmt hello.go
最終還是能再命令行里看到整潔的代碼
還截圖的效果,縮進(jìn)是8個(gè)字符的位置。
不過原文件里還是亂糟糟的,可以加上-w參數(shù),改寫原文件:
gofmt -w hello.go
實(shí)際寫到文件里,縮進(jìn)用的不是空格是Tab,具體效果是幾個(gè)字符就看文件的設(shè)置了。
另外換行是 \n
,這個(gè)windows的記事本下會(huì)用問題,記事本的換行是 \r\n
。
創(chuàng)建Go工作目錄:H:\Go\src\go_dev\day1\hello\。把之前寫的示例hello.go放到hello目錄下。再建個(gè)文件夾,其他示例的源文件放到examples目錄下。這里src文件夾的名字是不能變的,其他文件夾的名字包括上級(jí)的都隨意。
上面的演示都沒有對(duì)go的原文件進(jìn)行編譯,編譯要用 go build 命令:
H:\Go>go build go_dev\day1\hello
can't load package: package go_dev/day1/hello: cannot find package "go_dev/day1/hello" in any of:
D:\Go\src\go_dev\day1\hello (from $GOROOT)
C:\Users\Steed\go\src\go_dev\day1\hello (from $GOPATH)
H:\Go>
這里并沒有編譯成功,原因是找不到我們的源文件。之前因?yàn)闆]設(shè)置環(huán)境變量GOPATH,所以默認(rèn)沒有設(shè)置GOPATH就是把用戶家目錄作為GOPATH。這個(gè)GOPATH就是工作目錄。
先去把GOPATH的環(huán)境變量設(shè)置好,我這里 “H:\Go\“ 就是我的工作目錄,設(shè)置成:“H:\Go\“ 。建議設(shè)置用戶變量,當(dāng)然系統(tǒng)變量也沒問題。
完成之后要新開一個(gè)cmd,也有可能有要注銷當(dāng)前用戶,下次登錄才能完全生效。然后可以驗(yàn)證一下:
C:\Users\Steed>go env GOPATH
H:\Go\
然后再編譯一下,這次隨便找個(gè)目錄執(zhí)行命令:
J:\tmp>go build go_dev\day1\hello
J:\tmp>hello.exe
Hello World
命令執(zhí)行后會(huì)在當(dāng)前目錄下生成hello.exe的可執(zhí)行文件,上面也直接執(zhí)行了一下。文件名以及生成文件的路徑都是可以用參數(shù)指定的。
前面只所以不把所有的示例都放一起,是因?yàn)槠渌纠灿衜ain入口函數(shù),存在多個(gè)入口函數(shù)編譯會(huì)報(bào)錯(cuò)。
其實(shí)可以編譯單個(gè)文件,但是路徑要寫全(絕對(duì)路徑或相對(duì)路徑),單文件編譯似乎不受環(huán)境變量影響:
J:\tmp>go build H:\Go\src\go_dev\day1\hello\hello.go
復(fù)雜一點(diǎn)的程序一般都不是單個(gè)文件的,所以一個(gè)文件夾里就是一個(gè)小項(xiàng)目,只有一個(gè)入口函數(shù)。這樣編譯不會(huì)有問題。另外如果使用開發(fā)工具的話,這種情況開發(fā)工具直接也會(huì)提示錯(cuò)誤的。
最后,下面這么搞比較方便:
H:\Go\src>go build go_dev\day1\hello
H:\Go\src>go build go_dev\day1\hello\hello.go
選好cmd的啟動(dòng)路徑,之后源文件的路徑用Tab就能自動(dòng)補(bǔ)全出來了。
代碼不能單獨(dú)存在,任何代碼都屬于一個(gè)包。所以第一行代碼,一定寫的是package。
新建個(gè)文件夾package_exampl,寫一個(gè)由多個(gè)包多個(gè)文件構(gòu)成的代碼,具體如下:
// go_dev/day1/package_example/calc/add.go
package calc
func Add(x int, y int) int {
return x + y
}
// go_dev/day1/package_example/calc/sub.go
package calc
func Sub(x int, y int) int {
return x - y
}
// go_dev/day1/package_example/main/main.go
package main
import(
// "calc"
"go_dev/day1/package_example/calc"
"fmt"
)
func main(){
sum := calc.Add(100, 200)
sub := calc.Sub(10, 5)
fmt.Println(sum, sub)
}
calc包里的Add和Sub函數(shù)都是首字母大寫的。在Go語言里首字母大寫有特殊的意義,就是全局變量。如果都小寫的話,在main函數(shù)里這兩個(gè)函數(shù),由于作用域的問題,都是不可見的。
結(jié)論:就是說一個(gè)變量(包括函數(shù)),如果要被外部的包調(diào)用,必須要首字母大寫。不過變量不推薦這么做,因?yàn)檫@樣這個(gè)變量就是全局變量,而全局變量是不推薦使用的方法(別的語言里也同樣是不推薦使用全局變量的)。
main函數(shù)里導(dǎo)入包的時(shí)候,calc包的路徑要寫全,不能只寫 “calc” ,下面會(huì)具體分析。
編譯過程
先把import改成這樣,一步一步排錯(cuò):
import(
"calc"
// "go_dev/day1/package_example/calc"
"fmt"
)
多個(gè)包的編譯
H:\Go\src>go build go_dev\day1\package_example
can't load package: package go_dev/day1/package_example: no Go files in H:\Go\src\go_dev\day1\package_example
這里報(bào)錯(cuò),因?yàn)槲募A下確實(shí)沒有包,包的源文件在下一級(jí)的目錄里:
H:\Go\src>go build go_dev\day1\package_example\main
go_dev\day1\package_example\main\main.go:4:5: cannot find package "calc" in any of:
D:\Go\src\calc (from $GOROOT)
H:\Go\src\calc (from $GOPATH)
繼續(xù)報(bào)錯(cuò),這是找不到calc包,并且這里也看到了默認(rèn)查找包的路徑。現(xiàn)在包的路徑應(yīng)該怎么寫全就清除了,把import的內(nèi)容改回來,之后就能順利的編譯執(zhí)行了:
H:\Go\src>go build go_dev\day1\package_example\main
H:\Go\src>main.exe
300 5
指定路徑和文件名
一般編譯后生成的可執(zhí)行文件是放在工作目錄下的bin目錄下的。還是用go build命令,加上-o參數(shù),windows系統(tǒng)下得加上擴(kuò)展名exe之后才能執(zhí)行:
H:\Go\src>go build -o ../bin/test.exe go_dev\day1\package_example\main
H:\Go\src>cd ../bin
H:\Go\bin>test
300 5
H:\Go\bin>
程序分成2部分。一部分是業(yè)務(wù)邏輯,放在goroute目錄下。還有一部分是函數(shù)的入口,放在main目錄下。文件結(jié)構(gòu):
H:\GO\SRC\GO_DEV\DAY1\GOROUTE_EXAMPLE
├─goroute
└─main
業(yè)務(wù)邏輯就是,獲取3個(gè)變量,2個(gè)數(shù)和1個(gè)管道,把2個(gè)數(shù)的和計(jì)算后,存到管道里。
主函數(shù)里則是,單獨(dú)起一個(gè)線程goroute進(jìn)行計(jì)算,之后從管道里獲取到計(jì)算結(jié)果,打印出來。
這個(gè)例子里用到了線程goroute,以及管道用于goroute之間的通信。之前已經(jīng)演示過了,這里就是把代碼分成2個(gè)包再寫一遍:
// goroute/add.go
package goroute
func Add(a int, b int, c chan int){
sum := a + b
c <- sum
}
// goroute/main.go
package main
import(
"go_dev/day1/goroute_example/goroute"
"fmt"
)
func main(){
var pipe chan int
pipe = make(chan int, 1)
go goroute.Add(100, 200, pipe)
res := <- pipe
fmt.Println(res)
}
都是中文版的。
Go 語言之旅:https://tour.go-zh.org/welcome/1
Go 編程語言:https://go-zh.org/
Go 語言之旅可以作為入門教程,并且可以Web在線寫代碼,提交執(zhí)行在Web上顯示結(jié)果。
使用fmt分別打印字符串、二進(jìn)制、十進(jìn)制、十六進(jìn)制、浮點(diǎn)數(shù)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。