【golang】結構體及其方法的使用(struct)

函數是獨立的程序實體。我們可以聲明有名字的函數,也可以聲明沒名字的函數,還可以把它們當做普通的值傳來傳去。我們能把具有相同簽名的函數抽象成獨立的函數類型,以作為一組輸入、輸出(或者說一類邏輯組件)的代表。

方法卻不同,它需要有名字,不能被當作值來看待,最重要的是,它必須隸屬于某一個類型。方法所屬的類型會通過其聲明中的接收者(receiver)聲明體現出來。

接收者聲明就是在關鍵字func和方法名稱之間的圓括號包裹起來的內容,其中必須包含確切的名稱和類型字面量。

接收者的類型其實就是當前方法所屬的類型,而接收者的名稱,則用于在當前方法中引用它所屬的類型的當前值。

方法隸屬的類型其實并不局限于結構體類型,但必須是某個自定義的數據類型,并且不能是任何接口類型。

一個數據類型關聯的所有方法,共同組成了該類型的方法集合。同一個方法集合中的方法不能出現重名。并且,如果它們所屬的是一個結構體類型,那么它們的名稱與該類型中任何字段的名稱也不能重復。

我們可以把結構體類型中的一個字段看作是它的一個屬性或者一項數據,再把隸屬于它的一個方法看作是附加在其中數據之上的一個能力或者一項操作。將屬性及其能力(或者說數據及其操作)封裝在一起,是面向對象編程(object-oriented programming)的一個主要原則。

Go 語言攝取了面向對象編程中的很多優秀特性,同時也推薦這種封裝的做法。從這方面看,Go 語言其實是支持面向對象編程的,但它選擇摒棄了一些在實際運用過程中容易引起程序開發者困惑的特性和規則。

type AnimalCategory struct {kingdom string // 界。phylum string // 門。class string // 綱。order string // 目。family string // 科。genus string // 屬。species string // 種。
}category := AnimalCategory{species: "cat"}type Animal struct {
scientificName string // 學名。
AnimalCategory // 動物基本分類。
}animal := Animal{scientificName: "American Shorthair",AnimalCategory: category,
}
fmt.Printf("The animal: %s\n", animal)

上述代碼在后面使用fmt.Printf函數和%s占位符試圖打印animal的字符串表示形式,相當于調用animalString方法。雖然我們還沒有為Animal類型編寫String方法,但這樣做是沒問題的。因為在這里,嵌入字段AnimalCategoryString方法會被當做animal的方法調用。

那如果我也為Animal類型編寫一個String方法呢?這里會調用哪一個呢?

答案是,animal的String方法會被調用。這時,我們說,嵌入字段AnimalCategory的String方法被“屏蔽”了。注意,只要名稱相同,無論這兩個方法的簽名是否一致,被嵌入類型的方法都會“屏蔽”掉嵌入字段的同名方法

類似的,由于我們同樣可以像訪問被嵌入類型的字段那樣,直接訪問嵌入字段的字段,所以如果這兩個結構體類型里存在同名的字段,那么嵌入字段中的那個字段一定會被“屏蔽”。

正因為嵌入字段的字段和方法都可以“嫁接”到被嵌入類型上,所以即使在兩個同名的成員一個是字段,另一個是方法的情況下,這種“屏蔽”現象依然會存在。

不過,即使被屏蔽了,我們仍然可以通過鏈式的選擇表達式,選擇到嵌入字段的字段或方法,就像我在Category方法中所做的那樣。這種“屏蔽”其實還帶來了一些好處。我們看看下面這個Animal類型的String方法的實現:

func (a Animal) String() string {return fmt.Sprintf("%s (category: %s)",a.scientificName, a.AnimalCategory)
}

在這里,我們把對嵌入字段的String方法的調用結果融入到了Animal類型的同名方法的結果中。這種將同名方法的結果逐層“包裝”的手法是很常見和有用的,也算是一種慣用法了。

image.png

最后,還要提一下多層嵌入的問題。也就是說,嵌入字段本身也有嵌入字段的情況。請看我聲明的Cat類型:

type Cat struct {name stringAnimal
}
func (cat Cat) String() string {return fmt.Sprintf("%s (category: %s, name: %q)",cat.scientificName, cat.Animal.AnimalCategory, cat.name)
}

結構體類型Cat中有一個嵌入字段Animal,而Animal類型還有一個嵌入字段AnimalCategory
在這種情況下,“屏蔽”現象會以嵌入的層級為依據,嵌入層級越深的字段或方法越可能被“屏蔽”。

例如,當我們調用Cat類型值的String方法時,如果該類型確有String方法,那么嵌入字段AnimalAnimalCategoryString方法都會被“屏蔽”。

如果該類型沒有String方法,那么嵌入字段AnimalString方法會被調用,而它的嵌入字段AnimalCategoryString方法仍然會被屏蔽。

只有當Cat類型和Animal類型都沒有String方法的時候,AnimalCategoryString方法才被調用。
最后的最后,如果處于同一個層級的多個嵌入字段擁有同名的字段或方法,那么從被嵌入類型的值那里,選擇此名稱的時候就會引發一個編譯錯誤,因為編譯器無法確定被選擇的成員到底是哪一個。

Go語言是用嵌入字段實現了繼承嗎?

這里強調一下,Go 語言中根本沒有繼承的概念,它所做的是通過嵌入字段的方式實現了類型之間的組合。Go語言官網有關于這樣的說明。

簡單來說,面向對象編程中的繼承,其實是通過犧牲一定的代碼簡潔性來換取可擴展性,而且這種可擴展性是通過侵入的方式來實現的。

類型之間的組合采用的是非聲明的方式,我們不需要顯式地聲明某個類型實現了某個接口,或者一個類型繼承了另一個類型。

同時,類型組合也是非侵入式的,它不會破壞類型的封裝或加重類型之間的耦合。我們要做的只是把類型當做字段嵌入進來,然后坐享其成地使用嵌入字段所擁有的一切。如果嵌入字段有哪里不合心意,我們還可以用“包裝”或“屏蔽”的方式去調整和優化。

另外,類型間的組合也是靈活的,我們總是可以通過嵌入字段的方式把一個類型的屬性和能力“嫁接”給另一個類型。

這時候,被嵌入類型也就自然而然地實現了嵌入字段所實現的接口。再者,組合要比繼承更加簡潔和清晰,Go 語言可以輕而易舉地通過嵌入多個字段來實現功能強大的類型,卻不會有多重繼承那樣復雜的層次結構和可觀的管理成本。

接口類型之間也可以組合。在 Go 語言中,接口類型之間的組合甚至更加常見,我們常常以此來擴展接口定義的行為或者標記接口的特征。

值方法和指針方法都是什么意思,有什么區別?

  1. 值方法的接收者是該方法所屬的那個類型值的一個副本。我們在該方法內對該副本的修改一般都不會體現在原值上,除非這個類型本身是某個引用類型(比如切片或字典)的別名類型。

    而指針方法的接收者,是該方法所屬的那個基本類型值的指針值的一個副本。我們在這樣的方法內對該副本指向的值進行修改,卻一定會體現在原值上。

  2. 一個自定義數據類型的方法集合中僅會包含它的所有值方法,而該類型的指針類型的方法集合卻囊括了前者的所有方法,包括所有值方法和所有指針方法。

    嚴格來講,我們在這樣的基本類型的值上只能調用到它的值方法。但是,Go 語言會適時地為我們進行自動地轉譯,使得我們在這樣的值上也能調用到它的指針方法。

    比如,在Cat類型的變量cat之上,之所以我們可以通過cat.SetName(“monster”)修改貓的名字,是因為 Go 語言把它自動轉譯為了(&cat).SetName(“monster”),即:先取cat的指針值,然后在該指針值上調用SetName方法。

  3. 在后邊你會了解到,一個類型的方法集合中有哪些方法與它能實現哪些接口類型是息息相關的。如果一個基本類型和它的指針類型的方法集合是不同的,那么它們具體實現的接口類型的數量就也會有差異,除非這兩個數量都是零。

    比如,一個指針類型實現了某某接口類型,但它的基本類型卻不一定能夠作為該接口的實現類型。

文章學習自郝林老師的《Go語言36講》

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41381.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41381.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41381.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

爬蟲逆向實戰(八)--猿人學第十五題

一、數據接口分析 主頁地址:猿人學第十五題 1、抓包 通過抓包可以發現數據接口是api/match/15 2、判斷是否有加密參數 請求參數是否加密? 查看“載荷”模塊可以發現有一個m加密參數 請求頭是否加密? 無響應是否加密? 無cook…

CSS中的z-index屬性有什么作用?如何控制元素在層疊上下文中的顯示順序?

聚沙成塔每天進步一點點 ? 專欄簡介? z-index 屬性的作用及控制元素層疊順序作用 ? 控制元素層疊順序? 寫在最后 ? 專欄簡介 前端入門之旅:探索Web開發的奇妙世界 記得點擊上方或者右側鏈接訂閱本專欄哦 幾何帶你啟航前端之旅 歡迎來到前端入門之旅&#xff0…

管理類聯考——邏輯——真題篇——按知識分類——匯總篇——一、形式邏輯——選言——不相容選言——要么

第三節 不相容選言-要么-“要么A要么B”→A和B有且僅有一個 真題(2010-39)-不相容選言-要么-“要么A要么B”→A和B有且僅有一個 39.大小行星懸浮游在太陽系邊緣,極易受附近星體引力作用的影響。據研究人員計算,有時這些力量會將彗星從奧爾特星云拖出。這樣,它們更有可能…

WPF國際化的實現方法(WpfExtensions.Xaml)

https://blog.csdn.net/eyupaopao/article/details/120090431 resx資源文件實現 resx資源文件,實現的過程比第一種復雜,但resx文件本身編輯比較簡單,維護起來比較方便。需要用到的框架:WpfExtensions.Xaml 為每種語言添加.resx資…

Mac思維導圖軟件Xmind for Mac中文激活版

好的思維導圖軟件能幫助用戶更好的發揮創作能力,XMind是一款流行的思維導圖軟件,可以幫助用戶創建各種類型的思維導圖和概念圖。 多樣化的導圖類型:XMind提供了多種類型的導圖,如魚骨圖、樹形圖、機構圖等,可以滿足不同…

UI自動化測試常見的Exception

一. StaleElementReferenceException: - 原因:引用的元素已過期。原因是頁面刷新了,此時當然找不到之前頁面的元素。- 解決方案:不確定什么時候元素就會被刷新。頁面刷新后重新獲取元素的思路不變,這時可以使用python的…

ClickHouse(二十二):Clickhouse SQL DML操作及導入導出數據

進入正文前,感謝寶子們訂閱專題、點贊、評論、收藏!關注IT貧道,獲取高質量博客內容! 🏡個人主頁:含各種IT體系技術,IT貧道_Apache Doris,大數據OLAP體系技術棧,Kerberos安全認證-CSDN博客 &…

GPT-5出世?OpenAI GPT-5商標已注冊

OpenAI的GPT已經成為了業界標桿,升級速度之快讓人瞠目,別人追GPT-3.5的時候GPT-4橫空出世,差距被拉開了,現在GPT-5就要來了。 據商標律師泄露的消息,OpenAI已于7月18日注冊了GPT-5商標。雖然注冊商標并不罕見&#xf…

【【萌新的STM32學習-9】】

萌新的STM32學習-9 我們在使用某個外設,必須線使能該外設時鐘 SYSTEM 文件夾里面的代碼由正點原子提供,是 STM32F1xx 系列的底層核心驅動函數, 可以用在 STM32F1xx 系列的各個型號上面,方便大家快速構建自己的工程。本章&#xf…

基于IMX6ULLmini的linux裸機開發系列二:使用C語言和SDK點亮LED

引入sdk頭文件 sudo chown -R gec /opt 用這條命令給gec賦權限,否則訪問權限不夠,無法讀取,如下圖成功 目的:解決寄存器地址難查難設置 devices/MCIMX6Y2/MCIMX6Y2.h 記錄外設寄存器及其相關操作 devices/MCIMX6Y2/drivers/fsl_…

Windows+VMware+Ubuntu+Anaconda+VMware Tools

Q1:Windows不支持***agent模擬器 A1:在VMware安裝Ubuntu虛擬機 P1: 下載 VMware-workstation-full-15.5.6-16341506.exe 安裝包(峰哥電腦軟件) P2: 下載Ubuntu鏡像 地址 ubuntu-18.04.6-desktop-amd64.iso P3:搭載鏡…

干翻Dubbo系列第十一篇:Dubbo常見協議與通信效率對比

文章目錄 文章說明 一:協議 1:什么是協議 2:協議和序列化關系 3:協議組成 (一):頭信息 (二):體信息 4:Dubbo3中常見的協議 5:…

華為在ospf area 0單區域的情況下結合pbr對數據包的來回路徑進行控制

配置思路: 兩邊去的包在R1上用mqc進行下一跳重定向 兩邊回程包在R4上用mqc進行下一跳重定向 最終讓內網 192.168.10.0出去的數據包來回全走上面R-1-2-4 192.168.20.0出去的數據包來回全走 下面R1-3-4 R2和R3就是簡單ospf配置和宣告,其它沒有配置&#…

搭建grafana+loki+promtail日志收集系統

準備工作 下載地址 https://github.com/grafana/loki/releases 安裝包放在服務器目錄:/opt wget https://github.com/grafana/loki/releases/download/v2.4.2/loki-linux-amd64.zip wget https://github.com/grafana/loki/releases/download/v2.4.2/promtail-lin…

【備戰csp-j】csp常考題目詳解(3)

三.排列組合 1. 7名學生站成一排,甲、乙必須站在一起有多少不同排法? 答案:1440 解析: 6組人進行全排列:A(6,6); 甲和乙的順序有兩種情況,所以結果要再乘2; …

影響力再度提升,Smartbi多次蟬聯Gartner、IDC等權威認可

近期,思邁特軟件捷報頻傳,Smartbi憑借技術創新實力和產品能力,成功入選Gartner中國增強數據分析代表廠商及自助分析代表廠商,同時,連續三年蟬聯“IDC中國FinTech 50”榜單。 Part.1 再次被Gartner提名 Smartbi深度融…

重塑DTC規則:元氣森林的全渠道轉型

元氣森林作為迄今為止用5-6年時間最快達到70億年銷售額的飲料品牌(統一、可口可樂、東鵬特飲都花了15年左右,康師傅花了10年)。元氣森林于2016年在北京創立,憑借健康產品理念和新潮營銷方式,一款主打“0糖0卡0脂”概念…

激活函數總結(十一):激活函數補充(Absolute、Bipolar、Bipolar Sigmoid)

激活函數總結(十一):激活函數補充 1 引言2 激活函數2.1 Absolute激活函數2.2 Bipolar激活函數2.3 Bipolar Sigmoid激活函數 3. 總結 1 引言 在前面的文章中已經介紹了介紹了一系列激活函數 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、…

C++ auto關鍵字

文章目錄 一、auto的推導規則二、auto的限制 C11 中有:auto 類型推導 auto x 5; // OK: x 是 int 類型 auto pi new auto(1); // OK: pi 被推導為 int* const auto *v &x, u 6; // OK: v是const int*類型,u是const int類型 static auto y 0.0;…

【Java】批量生成條形碼-itextpdf

批量生成條形碼 Controller ApiOperation("商品一覽批量生成商品條形碼")PostMapping("/batchGenerateProdBarCode")public void batchGenerateProdBarCode(RequestBody ProductListCondition productListCondition,HttpServletResponse response){import…