專一於大數據及容器雲核心技術解密,可提供全棧的大數據+雲原平生臺諮詢方案,請持續關注本套博客。QQ郵箱地址:1120746959@qq.com,若有任何學術交流,可隨時聯繫。詳情請關注《數據雲技術社區》公衆號。 java
hello.go
package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Hello())
}
# 安裝GO 1.11及以上版本
go version
# 開啓module功能
export GO111MODULE=on
# 進入到項目目錄
cd /home/gopath/src/hello
# 初始化
go mod init
# 編譯
go build
#加載依賴包,自動歸檔到vendor目錄
go mod vendor -v
# 文件目錄結構
./
├── go.mod
├── go.sum
├── hello # 二進制文件
├── hello.go
└── vendor
├── golang.org
├── modules.txt
└── rsc.io
複製代碼
go get -u github.com/golang/dep/cmd/dep
#進入到項目目錄
cd /home/gopath/src/demo
#dep初始化,初始化配置文件Gopkg.toml
dep init
#dep加載依賴包,自動歸檔到vendor目錄
dep ensure
# 最終會生成vendor目錄,Gopkg.toml和Gopkg.lock的文件
複製代碼
一、單變量聲明,類型放在變量名以後,能夠爲任意類型
var 變量名 類型
二、多變量同類型聲明
var v1,v2,v3 string
三、多變量聲明
var {
v1 int
v2 []int
}
四、使用關鍵字var,聲明變量類型並賦值
var v1 int=10
五、使用關鍵字var,直接對變量賦值,go能夠自動推導出變量類型
var v2=10
六、直接使用「:=」對變量賦值,不使用var,二者同時使用會語法衝突,推薦使用
v3:=10
七、能夠限定常量類型,但非必需
const Pi float64 = 3.14
八、無類型常量和字面常量同樣
const zero=0.0
九、多常量賦值
const(
size int64=1024
eof=-1
)
十、常量的多重賦值,相似變量的多重賦值
const u,v float32=0,3
const a,b,c=3,4,"foo" //無類型常量的多重賦值
十一、常量賦值是編譯期行爲,能夠賦值爲一個編譯期運算的常量表達式
const mask=1<<3
複製代碼
//布爾類型的關鍵字爲bool,值爲true或false,不可寫爲0或1
var v1 bool
v1=true
//接受表達式判斷賦值,不支持自動或強制類型轉換
v2:=(1==2)
//int和int32爲不一樣類型,不會自動類型轉換須要強制類型轉換
//強制類型轉換需注意精度損失(浮點數→整數),值溢出(大範圍→小範圍)
var v2 int32
v1:=64
v2=int32(v1)
//浮點型分爲float32(相似C中的float),float64(相似C中的double)
var f1 float32
f1=12 //不加小數點,被推導爲整型
f2:=12.0 //加小數點,被推導爲float64
f1=float32(f2) //須要執行強制轉換
//複數的表示
var v1 complex64
v1=3.2+12i
//v1 v2 v3 表示爲同一個數
v2:=3.2+12i
v3:=complex(3.2,12)
//實部與虛部
//z=complex(x,y),經過內置函數實部x=real(z),虛部y=imag(z)
//聲明與賦值
var str string
str="hello world"
//建立數組
var array1 [5]int //聲明:var 變量名 類型
var array2 [5]int=[5]int{1,2,3,4,5} //初始化
array3:=[5]int{1,2,3,4,5} //直接用「:=」賦值
[3][5]int //二維數組
[3]*float //指針數組
//數組元素訪問
for i,v:=range array{
//第一個返回值爲數組下標,第二個爲元素的值
}
//建立切片,基於數組建立
var myArray [5]int=[5]{1,2,3,4,5}
var mySlice []int=myArray[first:last]
slice1=myArray[:] //基於數組全部元素建立
slice2=myArray[:3] //基於前三個元素建立
slice3=myArray[3:] //基於第3個元素開始後的全部元素建立
//直接建立
slice1:=make([]int,5) //元素初始值爲0,初始個數爲5
slice2:=make([]int,5,10) //元素初始值爲0,初始個數爲5,預留個數爲10
slice3:=[]int{1,2,3,4,5} //初始化賦值
//基於切片建立
oldSlice:=[]int{1,2,3,4,5}
newSlice:=oldSlice[:3] //基於切片建立,不能超過原切片的存儲空間(cap函數的值)
//動態增減元素,切片分存儲空間(cap)和元素個數(len),當存儲空間小於實際的元素個數,會從新分配一塊原空間2倍的內存塊,並將原數據複製到該內存塊中,合理的分配存儲空間能夠以空間換時間,下降系統開銷。
//添加元素
newSlice:=append(oldSlice,1,2,3) //直接將元素加進去,若存儲空間不夠會按上述方式擴容。
newSlice1:=append(oldSlice1,oldSlice2...) //將oldSlice2的元素打散後加到oldSlice1中,三個點不可省略。
//內容複製,copy()函數能夠複製切片,若是切片大小不同,按較小的切片元素個數進行復制
slice1:=[]int{1,2,3,4,5}
slice2:=[]int{6,7,8}
copy(slice2,slice1) //只會複製slice1的前三個元素到slice2中
copy(slice1,slice1) //只會複製slice2的三個元素到slice1中的前三個位置
//map先聲明後建立再賦值
var map1 map[鍵類型] 值類型
//建立
map1=make(map[鍵類型] 值類型)
map1=make(map[鍵類型] 值類型 存儲空間)
//賦值
map1[key]=value
// 直接建立
m2 := make(map[string]string)
// 而後賦值
m2["a"] = "aa"
m2["b"] = "bb"
// 初始化 + 賦值一體化
m3 := map[string]string{
"a": "aa",
"b": "bb",
}
//delete()函數刪除對應key的鍵值對,若是key不存在,不會報錯;若是value爲nil,則會拋出異常(panic)。
delete(map1,key)
//元素查找
value,ok:=myMap[key]
if ok{
//若是找到
//處理找到的value值
}
//遍歷
for key,value:=range myMap{
//處理key或value
}
複製代碼
//在if以後條件語句以前能夠添加變量初始化語句,用;號隔離
if <條件語句> { //條件語句不須要用括號括起來,花括號必須存在
//語句體
}else{
//語句體
}
//在有返回值的函數中,不容許將最後的return語句放在if...else...的結構中,不然會編譯失敗
//例如如下爲錯誤範例
func example(x int) int{
if x==0{
return 5
}else{
return x //最後的return語句放在if-else結構中,因此編譯失敗
}
}
複製代碼
//一、根據條件不一樣,對應不一樣的執行體
switch i{
case 0:
fmt.Printf("0")
case 1: //知足條件就會退出,只有添加fallthrough纔會繼續執行下一個case語句
fmt.Prinntf("1")
case 2,3,1: //單個case能夠出現多個選項
fmt.Printf("2,3,1")
default: //當都不知足以上條件時,執行default語句
fmt.Printf("Default")
}
//二、該模式等價於多個if-else的功能
switch {
case <條件表達式1>:
語句體1
case <條件表達式2>:
語句體2
}
複製代碼
//一、Go只支持for關鍵字,不支持while,do-while結構
for i,j:=0,1;i<10;i++{ //支持多個賦值
//語句體
}
//二、無限循環
sum:=1
for{ //不接條件表達式表示無限循環
sum++
if sum > 100{
break //知足條件跳出循環
}
}
//三、支持continue和break,break能夠指定中斷哪一個循環,break JLoop(標籤)
for j:=0;j<5;j++{
for i:=0;i<10;i++{
if i>5{
break JLoop //終止JLoop標籤處的外層循環
}
fmt.Println(i)
}
JLoop: //標籤處
...
複製代碼
//關鍵字goto支持跳轉
func myfunc(){
i:=0
HERE: //定義標籤處
fmt.Println(i)
i++
if i<10{
goto HERE //跳轉到標籤處
}
}
複製代碼
//一、函數組成:關鍵字func ,函數名,參數列表,返回值,函數體,返回語句
//先名稱後類型
func 函數名(參數列表)(返回值列表){ //參數列表和返回值列表以變量聲明的形式,若是單返回值能夠直接加類型
函數體
return //返回語句
}
//例子
func Add(a,b int)(ret int,err error){
//函數體
return //return語句
}
//二、函數調用
//先導入函數所在的包,直接調用函數
import "mymath"
sum,err:=mymath.Add(1,2) //多返回值和錯誤處理機制
複製代碼
//多返回值
func (file *File) Read(b []byte) (n int,err error)
//使用下劃線"_"來丟棄返回值
n,_:=f.Read(buf)
複製代碼
//匿名函數:不帶函數名的函數,能夠像變量同樣被傳遞。
func(a,b int,z float32) bool{ //沒有函數名
return a*b<int(z)
}
f:=func(x,y int) int{
return x+y
}
複製代碼
type Rect struct{ //定義矩形類
x,y float64 //類型只包含屬性,並無方法
width,height float64
}
func (r *Rect) Area() float64{ //爲Rect類型綁定Area的方法,*Rect爲指針引用能夠修改傳入參數的值
return r.width*r.height //方法歸屬於類型,不歸屬於具體的對象,聲明該類型的對象便可調用該類型的方法
}
複製代碼
type Integer int
func (a Integer) Less(b Integer) bool{ //表示a這個對象定義了Less這個方法,a能夠爲任意類型
return a<b
}
//類型基於值傳遞,若是要修改值須要傳遞指針
func (a *Integer) Add(b Integer){
*a+=b //經過指針傳遞來改變值
}
複製代碼
new()
func new(Type) *Type
內置函數 new 分配空間。傳遞給new 函數的是一個類型,不是一個值。返回值是指向這個新分配的零值的指針
//建立實例
rect1:=new(Rect) //new一個對象
rect2:=&Rect{} //爲賦值默認值,bool默認值爲false,int默認爲零值0,string默認爲空字符串
rect3:=&Rect{0,0,100,200} //取地址並賦值,按聲明的變量順序依次賦值
rect4:=&Rect{width:100,height:200} //按變量名賦值不按順序賦值
//構造函數:沒有構造參數的概念,一般由全局的建立函數NewXXX來實現構造函數的功能
func NewRect(x,y,width,height float64) *Rect{
return &Rect{x,y,width,height} //利用指針來改變傳入參數的值達到相似構造參數的效果
}
//方法的重載,Go不支持方法的重載(函數同名,參數不一樣)
//v …interface{}表示參數不定的意思,其中v是slice類型,及聲明不定參數,能夠傳入任意參數,實現相似方法的重載
func (poem *Poem) recite(v ...interface{}) {
fmt.Println(v)
}
複製代碼
func (base *Base) Foo(){...} //Base的Foo()方法
func (base *Base) Bar(){...} //Base的Bar()方法
type Foo struct{
Base //經過組合的方式聲明瞭基類,即繼承了基類
...
}
func (foo *Foo) Bar(){
foo.Base.Bar() //並改寫了基類的方法,該方法實現時先調用基類的Bar()方法
... //若是沒有改寫即爲繼承,調用foo.Foo()和調用foo.Base.Foo()的做用的同樣的
}
//修改內存佈局
type Foo struct{
... //其餘成員信息
Base
}
//以指針方式組合
type Foo struct{
*Base //以指針方式派生,建立Foo實例時,須要外部提供一個Base類實例的指針
...
}
//名字衝突問題,組合內外若是出現名字重複問題,只會訪問到最外層,內層會被隱藏,不會報錯,即相似java中方法覆蓋/重寫。
type X struct{
Name string
}
type Y struct{
X //Y.X.Name會被隱藏,內層會被隱藏
Name string //只會訪問到Y.Name,只會調用外層屬性
}
複製代碼
type Rect struct{
X,Y float64
Width,Height float64 //字母大寫開頭表示該屬性能夠由包外訪問到
}
func (r *Rect) area() float64{ //字母小寫開頭表示該方法只能包內調用
return r.Width*r.Height
}
複製代碼
type File struct{
//類的屬性
}
//File類的方法
func (f *File) Read(buf []byte) (n int,err error)
func (f *File) Write(buf []byte) (n int,err error)
func (f *File) Seek(off int64,whence int) (pos int64,err error)
func (f *File) Close() error
//接口1:IFile
type IFile interface{
Read(buf []byte) (n int,err error)
Write(buf []byte) (n int,err error)
Seek(off int64,whence int) (pos int64,err error)
Close() error
}
//接口2:IReader
type IReader interface{
Read(buf []byte) (n int,err error)
}
//接口賦值,File類實現了IFile和IReader接口,即接口所包含的全部方法
var file1 IFile = new(File)
var file2 IReader = new(File)
複製代碼
//接口animal
type Animal interface {
Speak() string
}
//Dog類實現animal接口
type Dog struct {
}
func (d Dog) Speak() string {
return "Woof!"
}
//Cat類實現animal接口
type Cat struct {
}
func (c Cat) Speak() string {
return "Meow!"
}
//Llama實現animal接口
type Llama struct {
}
func (l Llama) Speak() string {
return "?????"
}
//JavaProgrammer實現animal接口
type JavaProgrammer struct {
}
func (j JavaProgrammer) Speak() string {
return "Design patterns!"
}
//主函數
func main() {
animals := []Animal{Dog{}, Cat{}, Llama{}, JavaProgrammer{}} //利用接口實現多態
for _, animal := range animals {
fmt.Println(animal.Speak()) //打印不一樣實現該接口的類的方法返回值
}
}
複製代碼
//定義調用體
func Add(x,y int){
z:=x+y
fmt.Println(z)
}
//go關鍵字執行調用,即會產生一個goroutine併發執行
//當函數返回時,goroutine自動結束,若是有返回值,返回值會自動被丟棄
go Add(1,1)
//併發執行
func main(){
for i:=0;i<10;i++{//主函數啓動了10個goroutine,而後返回,程序退出,並不會等待其餘goroutine結束
go Add(i,i) //因此須要經過channel通訊來保證其餘goroutine能夠順利執行
}
}
複製代碼
//一、channel聲明,聲明一個管道chanName,該管道能夠傳遞的類型是ElementType
//管道是一種複合類型,[chan ElementType],表示能夠傳遞ElementType類型的管道[相似定語從句的修飾方法]
var chanName chan ElementType
var ch chan int //聲明一個能夠傳遞int類型的管道
var m map[string] chan bool //聲明一個map,值的類型爲能夠傳遞bool類型的管道
複製代碼
//緩衝機制
c:=make(chan int,1024) //第二個參數爲緩衝區大小,與切片的空間大小相似
//經過range關鍵字來實現依次讀取管道的數據,與數組或切片的range使用方法相似
for i :=range c{
fmt.Println("Received:",i)
}
//超時機制:利用select只要一個case知足,程序就繼續執行而不考慮其餘case的狀況的特性實現超時機制
timeout:=make(chan bool,1) //設置一個超時管道
go func(){
time.Sleep(1e9) //設置超時時間,等待一分鐘
timeout<-true //一分鐘後往管道放一個true的值
}()
//
select {
case <-ch: //若是讀到數據,則會結束select過程
//從ch中讀取數據
case <-timeout: //若是前面的case沒有調用到,一定會讀到true值,結束select,避免永久等待
//一直沒有從ch中讀取到數據,但從timeout中讀取到了數據
}
複製代碼
//管道寫入,把值想象成一個球,"<-"的方向,表示球的流向,ch即爲管道
//寫入時,當管道已滿(管道有緩衝長度)則會致使程序堵塞,直到有goroutine從中讀取出值
ch <- value
//管道讀取,"<-"表示從管道把球倒出來賦值給一個變量
//當管道爲空,讀取數據會致使程序阻塞,直到有goroutine寫入值
value:= <-ch
複製代碼
//每一個case必須是一個IO操做,面向channel的操做,只執行其中的一個case操做,一旦知足則結束select過程
//面向channel的操做無非三種狀況:成功讀出;成功寫入;即沒有讀出也沒有寫入
select{
case <-chan1:
//若是chan1讀到數據,則進行該case處理語句
case chan2<-1:
//若是成功向chan2寫入數據,則進入該case處理語句
default:
//若是上面都沒有成功,則進入default處理流程
}
複製代碼
P能夠偷任務(即goroutine),當某個P的本地G執行完,且全局沒有G須要執行的時候,P能夠去偷別的P尚未執行完的一半的G來給M執行,提升了G的執行效率。git
專一於大數據及容器雲核心技術解密,可提供全棧的大數據+雲原平生臺諮詢方案,請持續關注本套博客。QQ郵箱地址:1120746959@qq.com,若有任何學術交流,可隨時聯繫。詳情請關注《數據雲技術社區》公衆號。github