學習Golang書籍&資料: html
1. The Go Programming Language Specification: http://golang.org/ref/spec java
2. How to Write Go Code: http://golang.org/doc/code.html linux
3. Effective Go: http://golang.org/doc/effective_go.html git
4. Go語言編程.pdf github
5. Go語言程序設計.pdf golang
6. 學習GO語言.pdf 算法
7. Go語言·雲動力.pdf express
8. Go Web編程 編程
https://github.com/tiancaiamao/go-internals/tree/master/ebook
------------------------------------ windows
學習編程語言前,需明白:
一. 什麼是編程what is programming?
編程就是控制某種系統或工具實現具體功能或目標的過程. 至於哪一種系統, 哪一種工具, 什麼功能, 什麼目標? 由具體業務功能決定. 簡言之, 編程就是一種控制xx實現xx的過程.
二. 怎樣編程how to programming?
編程=算法+數據結構+語言
算法是控制實現過程的步驟序列.
數據結構是控制實現過程的數據方式,包括邏輯表示方式與物理存儲方式.
語言是控制實現過程的指令系統.
其中, 算法與數據結構都由語言來表達.
學習編程語言時,應按綱:
一. 設計目標
輕鬆編程, 快速編譯, 高效執行.
二. 運行機制
Golang是系統編程語言, 即Golang編程是控制系統實現功能.
源代碼compile by compier to generate目標代碼.
目標代碼link with native library to generate可執行程序
若是是虛擬機編程語言, 即控制虛擬機(間接控制系統)實現功能.
源代碼compile by compier to genrate字節碼.
虛擬機load class byte code to running.
靜態編譯型語言:
源代碼-->|被編譯器編譯|-->目標代碼-->|與本地庫連接|-->本地程序-->|控制系統實現功能|
動態解釋型語言:
源代碼-->|被編譯器編譯|-->字節碼-->|被虛擬機解釋|---->|控制系統實現功能|
相比可知: 動態解釋型語言,因爲虛擬機封裝底層系統應用,提供上層接口. 大大提升程序在不一樣系統之間的可移植性及一致性.
三. 語言特性
在Golang中, 主要的言特性:
類型後置
延遲函數: defer function & panic() & reconver
協程通訊: go router & channel
尾調用: It is already there in 6g/8g for certain cases, and in gccgo somewhat more generally.We do not currently plan to change the language to require that compilers implement tail call optimization in all cases. If you must have a tail call, you use a loop or a goto statement.
注意: Golang不支持尾調用. 要用goto來實現其效果.
--------------------------------------------
深刻後理解:
(1) 指針與反射: pointer & reflect
(2) 協程與通道: goroutine & channel
(3) 延遲與錯誤恢復: defer & panic(), reconver()
(4) 鬆接口與方法: loose interface
(5) 函數類型&多值返回: func type & multi-return value
四. 語法類庫, Golang的語法更像C+Python+Lua
1. 字符集
Golang使用Unicode字符集,UTF8編碼.內置包encoding/utf8提供字符集相關的操做.
2. 詞彙
2.1 保留字(Keyword): Golang保留字有20個:
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
能夠分紅3大類:
(1) 聲明定義: package, type, var const, func, chan
(2) 控制語句:
(2.1) 條件選擇: if-else, switch-case-default-fallthrough, select-case-default
(2.2) 循環迭代: for的三種形式:
for initial;condition;increment{...}
for initial;condition{...}
for {...}
(2.3) 跳轉中斷: break, continue, goto, return
(3) 特性操做: go, defer, import, range
2.2 標識符(Identity):
Golang的標識符由字母,數字,下劃線組成.
(1)而且不能數字打頭.
(2)不能與保留字相同.
Golang約定:
(1)公有標識符: 大寫字母打頭的標識符. 公有標識符能夠導出包外, 便可以包外訪問.
(2)私有標識符: 小寫字母或下劃線打頭的標識符, 私有標識符不能導出包外, 即只能包內訪問. 中文都是小寫字母, 都屬於私有標識符.
例如: const W全局變量 int = 123, 若是沒有W不能在包外訪問.
(3)下劃線(_)標識符: 自動捨棄賦值, 不供訪問. 不然"cannot use _ as value"
2.3 直接量(Literal):
直接量是值的數據表示形式.Golang的下述類型的直接量:
(1)指針類型: nil, 只有指針類型纔可能nil.
(2)bool類型: true, false
(3)int,intN,uint,uintN類型:
8進制0前綴
10進制無前綴
16進制0x前綴
注意: Golang的直接量不支持L,F後綴! 例如: var a int = 123L會報錯.
(4)floatN類型:
小數形式
指數形式
注意: Golang的直接量不支持L,F後綴! 例如: var a float32 = 123F會報錯.
(5)rune類型: 'C',單引括起來的單個字符或轉義序列.Golang支持的轉義序列:
\a U+0007 alert or bell
\b U+0008 backspace
\f U+000C form feed
\n U+000A line feed or newline
\r U+000D carriage return
\t U+0009 horizontal tab
\v U+000b vertical tab
\\ U+005c backslash
\' U+0027 single quote (valid escape only within rune literals)
\" U+0022 double quote (valid escape only within string literals)
(6)string類型: "...", `...`,雙引,反引括住的字符序列.
注意: Golang的字符串不能使用單引.
(7)array類型: {...}
(8)slice類型: []{...}
(9)map類型: {k=v...}
(10)struct類型: struct{...}
(11)interface類型: interface{...}
(12)func類型: func(){...},函數直接量
2.4 運算符(Operator):
(1)算術運算符
(2)比較運算符
(3)邏輯運算符
(4)位運算符
(5)賦值運算符
(6)逗號運算符
(7)條件運算符
(8)字串運算符
(9)地址運算符
(10)channel運算符
2.5 註釋符(Comment):
(1)單行註釋//
(2)多行註釋/*...*/
(3)文檔註釋,即組件定義前的註釋,可用godoc提取.
2.6 界定符: 詞彙的分隔符.
換行符(\n)或分號(;)表示語句結束.
續行符(\)取消換行: Golang沒有續行符
空格符(Space)
製表符(\t)
括弧: 圓括弧(...), 方括弧[...], 花括弧{...}
3. 數據類型, 直接量, 變量, 常量
數據類型運算:
x.(type)只能在switch結構使用,不然拋錯:use of .(type) outside type switch
defer func() {
if x := recover(); x != nil {
fmt.Printf("x=%v,m=%v\n", x.(type), x)
}
解決辦法: 使用felect.TypeOf(x)}()
數據結構指數據在計算機的邏輯表示與物理存儲方式.
數據類型指某類數據的值集及其操做集.抽象數據類型DAT表示爲(D,S,P),其中D表示該數據的值集,S表示該類數據的關係集,P表示該類數據的操做集.
直接量指值的數據表示.
變量指值會變的量.
常量指值會變的量.
C中定義變量,常量須要指定存儲類別, 數據類型. Golang沒有存儲類別, 類型聲明後置.
Golang約定:
(1)變量使用var顯式聲明,或用:=隱匿定義.
顯式聲明: var vname type=value隱式定義: vname:=value換言之 :=取代了var與type, 自動根據value推斷類型.
(2)常量使用const顯式聲明.
顯式聲明: const cname type=value
(3)Go支持分組聲明. 即同時聲明多個變量,常量或引入多個包. 在分組聲明中:
變量的缺省類型向後推斷, 即變量沒有指定類型時, 默認其後第一個顯式類型.
常量的缺省定義向前推斷, 即常量沒有指定定義時, 默認其前第一個顯式定義.
例如:
var(
a,
b,
c int; //則a,b,的類型默認爲c的類型.
)
const(
ac int = iota
bc //默認也是iota
cc //默認也是iota
)
(4) Go支持iota枚舉. 在const塊自動清0, 調用後自動加1.
Golang數據類型:
指針類型: nil
----------------------------------------
bool: true, false
integer:
int, int8, int16, int32, int64, rune
uint, uint8, uint16, uint32, uint64, byte
其中byte是uint8的別名, rune是int16的別名, 而byte, rune經常使用來表示字符.
float:
float32, float64
complex:
complex64, complex128
其中複數通常使用直接量RE+IMi或complex()函數初始化.例如:
var re float32 = 123
var im float32 = 34
var a complex64 = complex(re, im)
fmt.Println(a)
使用complex()函數,要求re,im的類型必須是float32或float64,並且必須相同.若是是float32,則生成complex64. 若是是float64,則生成complex128.
----------------------------------------
rune: 單引號括住的單個字符或轉義序列
string: 雙引,反引括住的字符序列. 其中反引取消換行與轉義符. 注意: 在Golang中string類型不支持單引! 例如:
var str1 string = `這\t是
一個
測試`
var str2 string = "這\t是"
var str3 string = '這\t是' //empty character literal or unescaped ' in character literal
fmt.Println(str1)
fmt.Println(str2)
fmt.Println(str3)
可使用encoding/utf8包來處理utf8編碼, 例如:
import fmt "fmt"
import "unicode/utf8"
func main() {
str := "dsjkdshd這是一個小小的測試sdh....js"
fmt.Printf("String %s\nLength: %d, Runes: %d\n", str, len(str), utf8.RuneCount([]byte(str)))
}
----------------------------------------
array: [xxx]type{...}, 注意: 在Golang中,
(1)array的長度是類型的組成部分, 不一樣長度表示不一樣類型. 例如:
var a [4]int = [...]int{1, 2, 3, 3}
var b [3]int = [...]int{3, 4, 5}
a = b //cannot use b (type [3]int) as type [4]int in assignment
(2)array直接量使用"..."表示array長度是元素個數. 注意: "..."只能用於array literal, 例如:
slice: []type{...}, slice底層封裝array, start, stop, copacity. slice會自動擴容.var b [...]int = [...]int{3, 4, 5}//var b [...]int = [...]int{3, 4, 5}
array與slice的區別:
(1)array必須指定長度,使用過程容量固定.
(2)slice不能指定長度,使用過程自動擴容, 但其底層(array,start,stop,capacity)會發生變化.
例如:
var arr [4]int //定義array
var sar []int = arr[:] //定義slice
sar2 := append(sar, 123) //擴容slice, 生成另外一個slice, 其底層(array, start, stop, capacity)也改變.
sar[0] = 112 //測試賦值
fmt.Println(arr[0]) //值爲112
fmt.Println(sar[0]) //值爲112
fmt.Println(sar2[0]) //值爲0
在Golang中, slice是套在array上的一個封裝器.
map: map[ktype]vtype{...}
map索引返回<value,status>, value表示鍵的值, status表示鍵的狀態(即鍵是否存在)!
chan: 在Golang中chan更像是C中的存儲類別. 例如 chan int ch=make(chan int).
在Golang中, slice, map, chan必須使用new(), make()函數來建立! 沒有規律, 實在蛋疼!
----------------------------------------
struct: 定義結構體
interface: 定義接口集
struct與interface的結合:
在Golang中, 使用struct+interface實現OO思想.
----------------------------------------
package:在Golang中, package與folder的名字能夠不一樣! 具體操做時, import的對象folder的相對路徑, 而代碼中引用倒是package. 固然, 可使用import <package> "path"方式來覆蓋默認的package. 這又何苦定義package? 另外, package支持層次嗎? 例如聲明package pk1.pk2
func: 支持func爲右值,卻無func類型, 即不能顯式聲明a爲func類型,哪麼a又是什麼類型?
a := func() {
str := "dsjkdshd這是一個小小的測試sdh....js"
fmt.Printf("String %s\nLength: %d, Runes: %d\n", str, len(str), utf8.RuneCount([]byte(str)))
}
a()
在Golang中,func支持閉包嗎?
----------------------------------------
簡結, 在Go1中, 類型系統雜亂無章, 無規可遁! 只能就近分組,方便記憶!
關於Golang數據類型的更深刻理解:
----------------------------------------
Golang的數據類型分3類(基本類型,複合類型,功能類型), 2種方式(值方式,指針方式)
值方式:
基本類型(Primitive type), 最基本的值類型
(1)布爾型: bool
(2)整型: int, intN, uint, uintN
(3)浮點型: floatN
(4)複數型: complexN
(5)字符型: byte, rune
(6)字串型: string
(6.1) 錯誤類型: error, Go內置error type以及errors package.
基本類型不能使用初始表{...}初始化!
複合類型(Composite type), 在基本類型上定義的複合值類型.
(1)數組類型: array
(2)切片類型: slice
(3)映射類型: map
(4)結構類型: struct
複合類型可使用初始表{...}初始化! 初始表有二種形式, 按順序, 或按索引.
功能類型(Function type), 在基本值類型,複合值類型上定義的功能類型.
指針方式: 每種值類型都有指針. Golang有指針類型,但沒有指針運算. 指針不是類型, 只是解決效率方式.(1)通道類型: chan
(2)函數類型: func
(3)接口類型: interface
行爲類型只提供某種行爲能力,不涉及數據. 通道類型在goroutine之間提供channel的行爲能力.但不涉及數據.
nil是指針類型的直接量. 只有指針類型才能賦值nil.interface類型的專有操做:
(1) Comma-ok斷言:
<interface>.(T)其中<interface>必須是interface類型.不然cannot type switch on non-interface value e (type Student)(2) switch測試:
switch <interface>.(type) {
case XXX:
interface陷阱: interface類型只能作爲參數類型, 不能作爲返回類型!}其中<interface>必須是interface類型. <interface>.(type)語法不能在switch外的任何邏輯裏面使用.
詳情: http://golang.org/doc/faq#nil_errorUnder the covers, interfaces are implemented as two elements, a type and a value. The value, called the interface's dynamic value, is an arbitrary concrete value and the type is that of the value. For the
int
value 3, an interface value contains, schematically, (int
,3
).An interface value is
nil
only if the inner value and type are both unset, (nil
,nil
). In particular, anil
interface will always hold anil
type. If we store a pointer of type*int
inside an interface value, the inner type will be*int
regardless of the value of the pointer: (*int
,nil
). Such an interface value will therefore be non-nil
even when the pointer inside isnil
.簡言之: 在Go中, interace的實現包含二個元素<type,value>, interface爲nil當且僅當<nil,nil>. 當聲明
已經變成了MyError<*MyErrorImpl,nil>, 故其作爲MyError返回已經再也不是nil. 解決辦法有二:var err *MyErrorImpl 或 var err *MyErrorImpl =nil時
(1)照官方說的, 先不聲明, return時先定義.(2)直接返回MyErrorImpl,即struct而不是interface示例:type Inf interface {Info() string}type InfImpl struct {info string}func (self *InfImpl) Info() string {return self.info}func returnInf() *InfImpl {var i *InfImpl = nilreturn i}func main() {fmt.Println("should nil")ri := returnInf()if ri != nil {fmt.Println("not nil")} else {fmt.Println("is nil")}}
4. 運算符, 內置函數, 表達式
運算符:
(1) Arithmetic operators: +, -, *, /, %
(2) Comparison operators: ==, !=, <, <=, >, >=
(3) Logical operators: !, &&, ||
(4) Address operators: &, *
(5) Receive operator: <-, 例如v2 = <-ch
(4) 位運算符: ~, &, |, ^
--------------------------
內置函數:
關於panic(),recover()的陷阱:
panic()會觸發程序中斷, 除非使用recover()恢復. 但recover()只是簡單返回panic()的參數. 僅僅根據result == nil判斷是否發生中斷, 會有陷阱. 由於panic(nil)觸發中斷,但其返回值倒是nil.
recover()最好也是result,ok:=recover(),後面ok表示是否觸發.
--------------------------
表達式:
(1)Method expressions
MethodExpr = ReceiverType "." MethodName .
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
更多參考<The Go Programming Language Specification>
5. 語句
5.1 表達式語句
5.2 空語句
5.3 語句塊/複合語句
5.4 控制語句
5.4.1 條件選擇:
if-else(三種形式)
switch-case-default-fallthrough(二種形式)
select-case-default
5.4.2 循環迭代
for(三種形式)
注意: Golang不支持do, while關鍵字. 迭代藉助range實現.
5.5 跳轉中斷:
break
continue
goto
return
fallthrough
5.6 異常處理:
defer,panic(),recover()
在Golang的條件選擇, 循環迭代中條件表達式均可省略(), 同時能夠包含初始化部分. 在初始化部分隱匿聲明的變量的做用域是其後的語句塊.
6. 函數
(1)語法定義
func (receiver ReceiveType) fname(param ParamType) ReturnType{
...
}
(2)形參聲明
普通形參: Go 支持普通參數
默認形參: Go不支持默認參數
變長形參: ..., Go支持變長參數, 等價slice, 可用range迭代. 其也表示unpack的意思.
多值返回: 若是聲明返回值變量,則不需顯式return.
(3)實參傳遞:
按位置傳遞: Go支持按位置傳遞.
按命名傳遞: Go不支持命名傳遞
變參傳遞: Go支持變參傳遞.
變參
接受不定數量的參數的函數叫作變參函數。定義函數使其接受變參:
func myfunc(arg ... i n t ) { }
arg ...int 告訴Go 這個函數接受不定數量的參數。注意,這些參數的類型所有是int。在函數體中,變量arg 是一個int 類型的slice:
f o r _, n := range arg {
fmt.Printf("And the number is: %d\n", n)
}
若是不想指定變參的類型,可用空接口interface{}(參閱第6 章)。假設有另外一個變參函數叫作myfunc2,下面的例子演示瞭如何向其傳遞變參:
func myfunc(arg ... i n t ) {
myfunc2(arg...) 按原樣傳遞
myfunc2(arg[:2]...) 傳遞部分
}
(4)內建函數:
close new panic complex
delete make recover real
len append print image
cap copy println
其中:
close: 用於channel通信,關閉channel.
delete: 用於刪除map中的元素.
len和cap: 返回string, slice, array, map的長度與容量.
new: 用於各類類型的內在分配,返回指針.
make: 用於map, slice, channel的初始化, 返回實例.
copy: 用於複製slice.
append: 用於追加slice.
panic和recover: 用於異常處理機制.
print和println: 用於底層打印函數, 可在不引入fmt包的狀況下使用. 主要用於調試.
complex, real和imag: 用於處理複數.
new()與make()的區別:
• new(T) 返回*T 指向一個零值T
• make(T) 返回初始化後的T
其中make 只能用於slice,map 和channel。
對於方法而言, 其聲明爲Type或者*Type好像都沒有侷限. 若是Type.proerty查不到,會自動(&T).property.沒有像C哪樣, 若是是指針則使用->.
main()函數與 init()函數:
(1)Go保留main()函數與init()函數. 每一個main package至少一個main()函數, 每一個package可有任意init()函數. 其執行順序參見下圖:
(2)函數數不能接收參數也不能返回值: func main must have no arguments and no return values
函數變量,函數常量,函數直接量,函數指針.:
任何直接量都不能使用&獲取地址.
/*
不能獲取函數的地址
var f *func(int) bool = &isOdd
cannot take the address of isOdd
但能夠賦給變量,而後取變量的地址.
var f func(int) bool = isOdd
odd := filter(&nums, &f)
這就像你試圖獲取直接量的地址:
func main() {
var pa *int = &345
fmt.Printf("even=%v\n", *pa)
}
cannot take the address of 345
*/
7. 高級特性
> CGO
> 指針: Go有指針,可是沒有指針運算. 你不能用指針變量遍歷字符串的各個字節.
8. 命名空間:包
定義包:
package <package_name>
加載包:
import <package_alias> "package_path",
必須注意: import "package_path", references <package_name >.
即import的值是path, 而references的值是name,
無論path仍是package都是相對$GOPATH.
其中可在import重命名package_name! 哪package <package_name>是否多餘了?
Golang的package與C++的namespace都是用於組織命名空間,避免命名衝突. 相同package下的變量能夠互相訪問.
包的操做:
9. 庫:內置包
參考<Directory /src/pkg>
10.程序結構
$GOPATH:
src: 源代碼
pkg: 依賴包
bin: 二進制
go命令的參數<package>映射爲$GOPATH/src/<package>,通常要求package xxx與目錄名相同! 但都習慣在目錄下面建立一個package main.用來作爲應用的入口.
五. 環境配置
1. 搭建開發環境
1). 安裝go 1.2 for windows
2). 安裝eclipse
3). 安裝goclipse
4). 安裝gocode
5). 安裝gdb
Linux下安裝Golang:
wget http://go.googlecode.com/files/go1.2.1.linux-amd64.tar.gz
tar -xzvf go1.2.1.linux-amd64.tar.gz -C /usr/local/
cd /usr/local/go/src
source all.bash
若是看到則表示成功:
ALL TESTS PASSED
---
Installed Go for linux/amd64 in /usr/local/go
Installed commands in /usr/local/go/bin
*** You need to add /usr/local/go/bin to your PATH.
2. 配置環境變量
#java
export JAVA_HOME=/usr/local/java
export PATH=$JAVA_HOME/bin:$PATH
#go
export GOROOT=/usr/local/go
export GOOS=linux
export GOARCH=amd64
#export GOBIN=$GOROOT/bin 影響go install
export GOTOOLS=$GOROOT/pkg/tool
export PATH=$PATH:$GOBIN:$GOTOOLS
3. 命令行及選項
go version
go env 列述GO環境變量
go get <packageUrl>
go install <package>: 不要隨便設置GOBIN, 使用go install命令會把編譯後的結果放到$GOBIN
go build <package>
go run <path>: 必須指定go文件的絕對路徑, 只是用做一次性測試.
go list <package>: 列出當前目錄或package下的可builtable的package
go test <package>: 執行對應package下面的測試程序,即以_test.go結尾的模塊.
--------------------------------------------------------
Go is a tool for managing Go source code.
Usage:
go command [arguments]
The commands are:
build compile packages and dependencies
clean remove object files
env print Go environment information
fix run go tool fix on packages
fmt run gofmt on package sources
get download and install packages and dependencies
install compile and install packages and dependencies
list list packages
run compile and run Go program
test test packages
tool run specified go tool
version print Go version
vet run go tool vet on packages
Use "go help [command]" for more information about a command.
Additional help topics:
c calling between Go and C
gopath GOPATH environment variable
importpath import path syntax
packages description of package lists
testflag description of testing flags
testfunc description of testing functions
Use "go help [topic]" for more information about that topic.