struct是Go中的關鍵字,用于定義結構類型。
在于田等地區(qū),都構建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都做網站、成都網站制作 網站設計制作按需定制制作,公司網站建設,企業(yè)網站建設,品牌網站建設,全網整合營銷推廣,外貿網站建設,于田網站建設費用合理。
例如:
struct {}是一個無元素的結構體類型,通常在沒有信息存儲時使用。優(yōu)點是大小為0,不需要內存來存儲struct {}類型的值。
struct {} {}是一個復合字面量,它構造了一個struct {}類型的值,該值也是空。
go中可以使用 unsafe.Sizeof 計算出一個數據類型實例需要占用的字節(jié)數。我們驗證一下:
也就是說空結構體實例不占用任何內存空間。
Go 語言標準庫沒有提供 Set 的實現,通常使用 map 來代替。事實上,對于集合來說,只需要 map 的鍵,而不需要值。
聲明為聲明為 map[string]struct{} ,由于struct{}是空,不關心內容,這樣map便改造為set 。
map可以通過“comma ok”機制來獲取該key是否存在,例如 _, ok := map["key"] ,如果沒有對應的值,ok為false。可以通過定義成 map[string]struct{} 的形式,值不再占用內存。其值僅有兩種狀態(tài),有或無。如果定義的是 map[string]bool ,則結果有true、false或沒有三種狀態(tài),而且即使是將值設置為 bool 類型,也會多占據 1 個字節(jié)。因此呢,將 map 作為集合(Set)使用時,可以將值類型定義為空結構體,僅作為占位符使用即可。
基于channels發(fā)送消息有兩個重要方面:發(fā)了消息、發(fā)了什么消息。一個強調了通訊的發(fā)生,一個強調了通訊的內容。當我們更希望強調通訊發(fā)生的時刻時,我們將它稱為 消息事件 。有些消息事件并不攜帶額外的信息,它僅僅是用作兩個goroutine之間的同步,這時候我們可以用 struct{} 空結構體作為channels元素的類型。用來通知子協(xié)程(goroutine)執(zhí)行任務,或只用來控制協(xié)程并發(fā)度。
在部分場景下,結構體只包含方法,不包含任何的字段。這時候我們就可以使用空結構體。
其實,上面的calculateInt 可以是任何類型,如 type calculateInt bool ,但是struct{}不占用任何空間,邏輯上也更合理,因此還是它最好。
1. 保留但大幅度簡化指針
Go語言保留著C中值和指針的區(qū)別,但是對于指針繁瑣用法進行了大量的簡化,引入引用的概念。所以在Go語言中,你幾乎不用擔心會因為直接操作內寸而引起各式各樣的錯誤。
2. 多參數返回
還記得在C里面為了回饋多個參數,不得不開辟幾段指針傳到目標函數中讓其操作么?在Go里面這是完全不必要的。而且多參數的支持讓Go無需使用繁瑣的exceptions體系,一個函數可以返回期待的返回值加上error,調用函數后立刻處理錯誤信息,清晰明了。
3. Array,slice,map等內置基本數據結構
如果你習慣了Python中簡潔的list和dict操作,在Go語言中,你不會感到孤單。一切都是那么熟悉,而且更加高效。如果你是C++程序員,你會發(fā)現你又找到了STL的vector 和 map這對朋友。
4. Interface
Go語言最讓人贊嘆不易的特性,就是interface的設計。任何數據結構,只要實現了interface所定義的函數,自動就implement了這個interface,沒有像Java那樣冗長的class申明,提供了靈活太多的設計度和OO抽象度,讓你的代碼也非常干凈。千萬不要以為你習慣了Java那種一條一條加implements的方式,感覺還行,等接口的設計越來越復雜的時候,無數Bug正在后面等著你。
同時,正因為如此,Go語言的interface可以用來表示任何generic的東西,比如一個空的interface,可以是string可以是int,可以是任何數據類型,因為這些數據類型都不需要實現任何函數,自然就滿足空interface的定義了。加上Go語言的type assertion,可以提供一般動態(tài)語言才有的duck typing特性, 而仍然能在compile中捕捉明顯的錯誤。
5. OO
Go語言本質上不是面向對象語言,它還是過程化的。但是,在Go語言中, 你可以很輕易的做大部分你在別的OO語言中能做的事,用更簡單清晰的邏輯。是的,在這里,不需要class,仍然可以繼承,仍然可以多態(tài),但是速度卻快得多。因為本質上,OO在Go語言中,就是普通的struct操作。
6. Goroutine
這個幾乎算是Go語言的招牌特性之一了,我也不想多提。如果你完全不了解Goroutine,那么你只需要知道,這玩意是超級輕量級的類似線程的東西,但通過它,你不需要復雜的線程操作鎖操作,不需要care調度,就能玩轉基本的并行程序。在Go語言里,觸發(fā)一個routine和erlang spawn一樣簡單?;旧弦莆誈o語言,以Goroutine和channel為核心的內存模型是必須要懂的。不過請放心,真的非常簡單。
7. 更多現代的特性
和C比較,Go語言完全就是一門現代化語言,原生支持的Unicode, garbage collection, Closures(是的,和functional programming language類似), function是first class object,等等等等。
看到這里,你可能會發(fā)現,我用了很多輕易,簡單,快速之類的形容詞來形容Go語言的特點。我想說的是,一點都不夸張,連Go語言的入門學習到提高,都比別的語言門檻低太多太多。在大部分人都有C的背景的時代,對于Go語言,從入門到能夠上手做項目,最多不過半個月。Go語言給人的感覺就是太直接了,什么都直接,讀源代碼直接,寫自己的代碼也直接。
作為C語言家族的一員,go和c一樣也支持結構體??梢灶惐扔趈ava的一個POJO。
在學習定義結構體之前,先學習下定義一個新類型。
新類型 T1 是基于 Go 原生類型 int 定義的新自定義類型,而新類型 T2 則是 基于剛剛定義的類型 T1,定義的新類型。
這里要引入一個底層類型的概念。
如果一個新類型是基于某個 Go 原生類型定義的, 那么我們就叫 Go 原生類型為新類型的底層類型
在上面的例子中,int就是T1的底層類型。
但是T1不是T2的底層類型,只有原生類型才可以作為底層類型,所以T2的底層類型還是int
底層類型是很重要的,因為對兩個變量進行顯式的類型轉換,只有底層類型相同的變量間才能相互轉換。底層類型是判斷兩個類型本質上是否相同的根本。
這種類型定義方式通常用在 項目的漸進式重構,還有對已有包的二次封裝方面
類型別名表示新類型和原類型完全等價,實際上就是同一種類型。只不過名字不同而已。
一般我們都是定義一個有名的結構體。
字段名的大小寫決定了字段是否包外可用。只有大寫的字段可以被包外引用。
還有一個點提一下
如果換行來寫
Age: 66,后面這個都好不能省略
還有一個點,觀察e3的賦值
new返回的是一個指針。然后指針可以直接點號賦值。這說明go默認進行了取值操作
e3.Age 等價于 (*e3).Age
如上定義了一個空的結構體Empty。打印了元素e的內存大小是0。
有什么用呢?
基于空結構體類型內存零開銷這樣的特性,我們在日常 Go 開發(fā)中會經常使用空 結構體類型元素,作為一種“事件”信息進行 Goroutine 之間的通信
這種以空結構體為元素類建立的 channel,是目前能實現的、內存占用最小的 Goroutine 間通信方式。
這種形式需要說的是幾個語法糖。
語法糖1:
對于結構體字段,可以省略字段名,只寫結構體名。默認字段名就是結構體名
這種方式稱為 嵌入字段
語法糖2:
如果是以嵌入字段形式寫的結構體
可以省略嵌入的Reader字段,而直接訪問ReaderName
此時book是一個各個屬性全是對應類型零值的一個實例。不是nil。這種情況在Go中稱為零值可用。不像java會導致npe
結構體定義時可以在字段后面追加標簽說明。
tag的格式為反單引號
tag的作用是可以使用[反射]來檢視字段的標簽信息。
具體的作用還要看使用的場景。
比如這里的tag是為了幫助 encoding/json 標準包在解析對象時可以利用的規(guī)則。比如omitempty表示該字段沒有值就不打印出來。
對于某些類型的變量,如指針、切片、map、接口、通道、函數等,如果從未為它賦過值,則它將具有默認值nil。這句代碼的意思就是,如果s0未初始化過,就打印true,否則打印false。
你說的應該是這樣:
var?User?interface{}
這個是空接口,代表任意類型的意思,因為所有類型都滿足空接口