十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
Go語言由Google公司開發(fā),并于2009年開源,相比Java/Python/C等語言,Go尤其擅長并發(fā)編程,性能堪比C語言,開發(fā)效率肩比Python,被譽為“21世紀的C語言”。

創(chuàng)新互聯(lián)建站"三網(wǎng)合一"的企業(yè)建站思路。企業(yè)可建設擁有電腦版、微信版、手機版的企業(yè)網(wǎng)站。實現(xiàn)跨屏營銷,產(chǎn)品發(fā)布一步更新,電腦網(wǎng)絡+移動網(wǎng)絡一網(wǎng)打盡,滿足企業(yè)的營銷需求!創(chuàng)新互聯(lián)建站具備承接各種類型的成都網(wǎng)站設計、成都網(wǎng)站建設、外貿(mào)網(wǎng)站建設項目的能力。經(jīng)過10余年的努力的開拓,為不同行業(yè)的企事業(yè)單位提供了優(yōu)質(zhì)的服務,并獲得了客戶的一致好評。
Go語言在云計算、大數(shù)據(jù)、微服務、高并發(fā)領域應用應用非常廣泛。BAT大廠正在把Go作為新項目開發(fā)的首選語言。
Go語言能干什么?
1、服務端開發(fā):以前你使用C或者C++做的那些事情,用Go來做很合適,例如日志處理、文件系統(tǒng)、監(jiān)控系統(tǒng)等;
2、DevOps:運維生態(tài)中的Docker、K8s、prometheus、grafana、open-falcon等都是使用Go語言開發(fā);
3、網(wǎng)絡編程:大量優(yōu)秀的Web框架如Echo、Gin、Iris、beego等,而且Go內(nèi)置的 net/http包十分的優(yōu)秀;
4、Paas云平臺領域:Kubernetes和Docker Swarm等;
5、分布式存儲領域:etcd、Groupcache、TiDB、Cockroachdb、Influxdb等;
6、區(qū)塊鏈領域:區(qū)塊鏈里面有兩個明星項目以太坊和fabric都使用Go語言;
7、容器虛擬化:大名鼎鼎的Docker就是使用Go語言實現(xiàn)的;
8、爬蟲及大數(shù)據(jù):Go語言天生支持并發(fā),所以十分適合編寫分布式爬蟲及大數(shù)據(jù)處理。
字段標簽允許您將元信息附加到可以使用反射獲取的字段上。通常,它用于提供有關如何將結(jié)構域編碼為另一種格式(或從另一種格式存儲(或從數(shù)據(jù)庫中檢索))的轉(zhuǎn)換信息,但是您可以使用它存儲想要存儲的任何元信息,這些元信息既可以用于另一種包裝或供您自己使用。
如的文檔所述reflect.StructTag,按照慣例,標記字符串的值是用空格分隔的key:"value"成對列表,如:
type User struct {
Name string `json:"name" xml:"name"`
}
的key通常表示包,隨后的"value"是,如json密鑰被處理/使用的encoding/json包。
如果要在中傳遞多個信息"value",通常通過用逗號(',')隔開來指定它,如
Name string `json:"name,omitempty" xml:"name"`
通常用破折號('-')"value"表示將字段從過程中排除(如,在這種情況下,json表示不封送或取消封送該字段)。
使用反射訪問自定義標簽的示例
我們可以使用反射(reflect包)來訪問結(jié)構字段的標記值?;旧希覀冃枰@取Type結(jié)構的,然后可以使用Type.Field(i
int)或查詢字段Type.FieldByName(name
string)。這些方法返回的值StructField描述/表示一個struct字段;并且StructField.Tag是StructTag描述/表示標記值的類型值。
以前我們談論過 “慣例” 。該公約的手段,如果你遵循它,你可以使用StructTag.Get(key
string)它解析變量的值,并返回該方法"value"的key指定。該公約實施/內(nèi)置到這個Get()方法。如果不遵守約定,Get()將無法解析key:"value"對并找到您要查找的內(nèi)容。這也不是問題,但是隨后您需要實現(xiàn)自己的解析邏輯。
還有StructTag.Lookup()(在Go1.7中添加了),它 “類似于,Get()但是將不包含給定鍵的標簽與將空字符串與給定鍵相關聯(lián)的標簽區(qū)分開”。因此,看一個簡單的示例:
type User struct {
Name ?string `mytag:"MyName"`
Email string `mytag:"MyEmail"`}
u := User{"Bob", "bob@mycompany.com"}
t := reflect.TypeOf(u)for _, fieldName := range []string{"Name", "Email"} {
field, found := t.FieldByName(fieldName) ? ?if !found { ? ? ? ?continue
}
fmt.Printf("\nField: User.%s\n", fieldName)
fmt.Printf("\tWhole tag value : %q\n", field.Tag)
fmt.Printf("\tValue of 'mytag': %q\n", field.Tag.Get("mytag"))
}
輸出(在Go Playground上嘗試):
Field: User.Name
Whole tag value : "mytag:\"MyName\""
Value of 'mytag': "MyName"Field: User.Email
Whole tag value : "mytag:\"MyEmail\""
Value of 'mytag': "MyEmail"
GopherCon 2015上有一個關于struct標簽的演示,名為:結(jié)構標簽的許多面孔(幻燈片)
(和視頻)以下是常用標簽鍵的列表:
json-由encoding/json包裝使用,詳細說明json.Marshal()
xml-由encoding/xml包裝使用,詳細說明xml.Marshal()
bson-由gobson使用,詳細說明bson.Marshal()
protobuf-由github.com/golang/protobuf/proto,在軟件包doc中有詳細說明
yaml-由gopkg.in/yaml.v2包裝使用,詳細說明yaml.Marshal()
db-由github.com/jmoiron/sqlx包裝使用;也被github.com/go-gorp/gorp包裝使用
orm-由github.com/astaxie/beego/orm包裝使用,在“ 型號– Beego ORM”中有詳細說明
gorm-由github.com/jinzhu/gorm軟件包使用,示例可在其文檔中找到:模型
valid-由github.com/asaskevich/govalidator軟件包使用,示例可以在項目頁面中找到
datastore-由appengine/datastore(Google App Engine平臺,數(shù)據(jù)存儲區(qū)服務)使用,在“ 屬性”中有詳細說明
schema-用于通過HTML表單值github.com/gorilla/schema填充(struct包文檔中有詳細說明)
asn-由encoding/asn1包裝使用,詳細說明在asn1.Marshal()和asn1.Unmarshal()
csv-由github.com/gocarina/gocsv包裝使用
目錄
一、結(jié)構體詳解
1. 結(jié)構體定義
2. 實例化結(jié)構體的7種方法
二、結(jié)構體方法
1. 結(jié)構體的方法定義
2. 結(jié)構體內(nèi)自定義方法的引用
3. 任意類型添加方法
三、嵌套、繼承
1. 匿名結(jié)構體
2. 結(jié)構體中可以定義任意類型的字段
3. 結(jié)構體嵌套結(jié)構體
4. 結(jié)構體嵌套匿名結(jié)構體
5. 結(jié)構體嵌套多個匿名結(jié)構體
6. 結(jié)構體繼承
四、結(jié)構體和JSON相互轉(zhuǎn)換
1. 結(jié)構體轉(zhuǎn)化成json
2. json轉(zhuǎn)化成結(jié)構體
3. 結(jié)構體標簽 tag
4. 嵌套結(jié)構體和json的序列化反序列化
Golang 中沒有“類”的概念,Golang 中的結(jié)構體和其他語言中的類有點相似。和其他面向?qū)?象語言中的類相比,Golang 中的結(jié)構體具有更高的擴展性和靈活性。
Golang 中的基礎數(shù)據(jù)類型可以表示一些事物的基本屬性,但是當我們想表達一個事物的全 部或部分屬性時,這時候再用單一的基本數(shù)據(jù)類型就無法滿足需求了,Golang 提供了一種 自定義數(shù)據(jù)類型,可以封裝多個基本數(shù)據(jù)類型,這種數(shù)據(jù)類型叫結(jié)構體,英文名稱 struct。 也就是我們可以通過 struct 來定義自己的類型了。
使用 type 和 struct 關鍵字來定義結(jié)構體,具體代碼格式如下:
type 類型名 struct {
字段名 字段類型
字段名 字段類型 …
}
其中:
? 類型名:表示自定義結(jié)構體的名稱,在同一個包內(nèi)不能重復。
? 字段名:表示結(jié)構體字段名。結(jié)構體中的字段名必須唯一。
? 字段類型:表示結(jié)構體字段的具體類型。
在 go 語言中,沒有類的概念但是可以給類型(結(jié)構體,自定義類型)定義方法。所謂方法 就是定義了接收者的函數(shù)。接收者的概念就類似于其他語言中的 this 或者 self。
方法的定義格式如下:
func (接收者變量 接收者類型) 方法名(參數(shù)列表) (返回參數(shù)) {
函數(shù)體
}
注意:想改變結(jié)構體內(nèi)的值,必須先變成指針。
在 Go 語言中,接收者的類型可以是任何類型,不僅僅是結(jié)構體,任何類型都可以擁有方法。 舉個例子,我們基于內(nèi)置的 int 類型使用 type 關鍵字可以定義新的自定義類型,然后為我們 的自定義類型添加方法。
注意:匿名結(jié)構體中不允許出現(xiàn)多個重復的類型
注意:如果結(jié)構體里面有私有屬性也就是小寫定義的字段,則不會被json使用
Go語言作為出現(xiàn)比較晚的一門編程語言,在其原生支持高并發(fā)、云原生等領域的優(yōu)秀表現(xiàn),像目前比較流行的容器編排技術Kubernetes、容器技術Docker都是用Go語言寫的,像Java等其他面向?qū)ο蟮恼Z言,雖然也能做云原生相關的開發(fā),但是支持的程度遠沒有Go語言高,憑借其語言特性和簡單的編程方式,彌補了其他編程語言一定程度上的不足,一度成為一個熱門的編程語言。
最近在學習Go語言,我之前使用過C#、Java等面向?qū)ο缶幊痰恼Z言,發(fā)現(xiàn)其中有很多的編程方式和其他語言有區(qū)別的地方,好記性不如爛筆頭,總結(jié)一下,和其他語言做個對比。這里只總結(jié)差異的地方,具體的語法不做詳細的介紹。
種一棵樹最好的時間是十年前,其次是現(xiàn)在。
3)變量初始化時候可以和其他語言一樣直接在變量后面加等號,等號后面為要初始化的值,也可以使用變量名:=變量值的簡單方式
3)變量賦值 Go語言的變量賦值和多數(shù)語言一致,但是Go語言提供了多重賦值的功能,比如下面這個交換i、j變量的語句:
在不支持多重賦值的語言中,交換兩個變量的值需要引入一個中間變量:
4)匿名變量
在使用其他語言時,有時候要獲取一個值,卻因為該函數(shù)返回多個值而不得不定義很多沒有的變量,Go語言可以借助多重返回值和匿名變量來避免這種寫法,使代碼看起來更優(yōu)雅。
假如GetName()函數(shù)返回3個值,分別是firstName,lastName和nickName
若指向獲得nickName,則函數(shù)調(diào)用可以這樣寫
這種寫法可以讓代碼更清晰,從而大幅降低溝通的復雜度和維護的難度。
1)基本常量
常量使用關鍵字const 定義,可以限定常量類型,但不是必須的,如果沒有定義常量的類型,是無類型常量
2)預定義常量
Go語言預定義了這些常量 true、false和iota
iota比較特殊,可以被任務是一個可被編譯器修改的常量,在每個const關鍵字出現(xiàn)時被重置為0,然后在下一個const出現(xiàn)之前每出現(xiàn)一個iota,其所代表的數(shù)字會自動加1.
3)枚舉
1)int 和int32在Go語言中被認為是兩種不同類型的類型
2)Go語言定義了兩個浮點型float32和float64,其中前者等價于C語言的float類型,后者等價于C語言的double類型
3)go語言支持復數(shù)類型
復數(shù)實際上是由兩個實數(shù)(在計算機中使用浮點數(shù)表示)構成,一個表示實部(real)、一個表示虛部(imag)。也就是數(shù)學上的那個復數(shù)
復數(shù)的表示
實部與虛部
對于一個復數(shù)z=complex(x,y),就可以通過Go語言內(nèi)置函數(shù)real(z)獲得該復數(shù)的實部,也就是x,通過imag(z)獲得該復數(shù)的虛部,也就是y
4)數(shù)組(值類型,長度在定義后無法再次修改,每次傳遞都將產(chǎn)生一個副本。)
5)數(shù)組切片(slice)
數(shù)組切片(slice)彌補了數(shù)組的不足,其數(shù)據(jù)結(jié)構可以抽象為以下三個變量:
6)Map 在go語言中Map不需要引入任何庫,使用很方便
Go循環(huán)語句只支持for關鍵字,不支持while和do-while
goto語句的語義非常簡單,就是跳轉(zhuǎn)到本函數(shù)內(nèi)的某個標簽
今天就介紹到這里,以后我會在總結(jié)Go語言在其他方面比如并發(fā)編程、面向?qū)ο蟆⒕W(wǎng)絡編程等方面的不同及使用方法。希望對大家有所幫助。
作為C語言家族的一員,go和c一樣也支持結(jié)構體??梢灶惐扔趈ava的一個POJO。
在學習定義結(jié)構體之前,先學習下定義一個新類型。
新類型 T1 是基于 Go 原生類型 int 定義的新自定義類型,而新類型 T2 則是 基于剛剛定義的類型 T1,定義的新類型。
這里要引入一個底層類型的概念。
如果一個新類型是基于某個 Go 原生類型定義的, 那么我們就叫 Go 原生類型為新類型的底層類型
在上面的例子中,int就是T1的底層類型。
但是T1不是T2的底層類型,只有原生類型才可以作為底層類型,所以T2的底層類型還是int
底層類型是很重要的,因為對兩個變量進行顯式的類型轉(zhuǎn)換,只有底層類型相同的變量間才能相互轉(zhuǎn)換。底層類型是判斷兩個類型本質(zhì)上是否相同的根本。
這種類型定義方式通常用在 項目的漸進式重構,還有對已有包的二次封裝方面
類型別名表示新類型和原類型完全等價,實際上就是同一種類型。只不過名字不同而已。
一般我們都是定義一個有名的結(jié)構體。
字段名的大小寫決定了字段是否包外可用。只有大寫的字段可以被包外引用。
還有一個點提一下
如果換行來寫
Age: 66,后面這個都好不能省略
還有一個點,觀察e3的賦值
new返回的是一個指針。然后指針可以直接點號賦值。這說明go默認進行了取值操作
e3.Age 等價于 (*e3).Age
如上定義了一個空的結(jié)構體Empty。打印了元素e的內(nèi)存大小是0。
有什么用呢?
基于空結(jié)構體類型內(nèi)存零開銷這樣的特性,我們在日常 Go 開發(fā)中會經(jīng)常使用空 結(jié)構體類型元素,作為一種“事件”信息進行 Goroutine 之間的通信
這種以空結(jié)構體為元素類建立的 channel,是目前能實現(xiàn)的、內(nèi)存占用最小的 Goroutine 間通信方式。
這種形式需要說的是幾個語法糖。
語法糖1:
對于結(jié)構體字段,可以省略字段名,只寫結(jié)構體名。默認字段名就是結(jié)構體名
這種方式稱為 嵌入字段
語法糖2:
如果是以嵌入字段形式寫的結(jié)構體
可以省略嵌入的Reader字段,而直接訪問ReaderName
此時book是一個各個屬性全是對應類型零值的一個實例。不是nil。這種情況在Go中稱為零值可用。不像java會導致npe
結(jié)構體定義時可以在字段后面追加標簽說明。
tag的格式為反單引號
tag的作用是可以使用[反射]來檢視字段的標簽信息。
具體的作用還要看使用的場景。
比如這里的tag是為了幫助 encoding/json 標準包在解析對象時可以利用的規(guī)則。比如omitempty表示該字段沒有值就不打印出來。