golang例子,Golang語法

本文目錄一覽:

golang中級進階(二):結構體

目錄

一、結構體詳解

1. 結構體定義

2. 實例化結構體的7種方法

二、結構體方法

1. 結構體的方法定義

2. 結構體內自定義方法的引用

3. 任意類型添加方法

三、嵌套、繼承

1. 匿名結構體

2. 結構體中可以定義任意類型的字段

3. 結構體嵌套結構體

4. 結構體嵌套匿名結構體

5. 結構體嵌套多個匿名結構體

6. 結構體繼承

四、結構體和JSON相互轉換

1. 結構體轉化成json

2. json轉化成結構體

3. 結構體標籤 tag

4. 嵌套結構體和json的序列化反序列化

Golang 中沒有“類”的概念,Golang 中的結構體和其他語言中的類有點相似。和其他面向對 象語言中的類相比,Golang 中的結構體具有更高的擴展性和靈活性。

Golang 中的基礎數據類型可以表示一些事物的基本屬性,但是當我們想表達一個事物的全 部或部分屬性時,這時候再用單一的基本數據類型就無法滿足需求了,Golang 提供了一種 自定義數據類型,可以封裝多個基本數據類型,這種數據類型叫結構體,英文名稱 struct。 也就是我們可以通過 struct 來定義自己的類型了。

使用 type 和 struct 關鍵字來定義結構體,具體代碼格式如下:

type 類型名 struct {

字段名 字段類型

字段名 字段類型 …

}

其中:

• 類型名:表示自定義結構體的名稱,在同一個包內不能重複。

• 字段名:表示結構體字段名。結構體中的字段名必須唯一。

• 字段類型:表示結構體字段的具體類型。

在 go 語言中,沒有類的概念但是可以給類型(結構體,自定義類型)定義方法。所謂方法 就是定義了接收者的函數。接收者的概念就類似於其他語言中的 this 或者 self。

方法的定義格式如下:

func (接收者變量 接收者類型) 方法名(參數列表) (返回參數) {

函數體

}

注意:想改變結構體內的值,必須先變成指針。

在 Go 語言中,接收者的類型可以是任何類型,不僅僅是結構體,任何類型都可以擁有方法。 舉個例子,我們基於內置的 int 類型使用 type 關鍵字可以定義新的自定義類型,然後為我們 的自定義類型添加方法。

注意:匿名結構體中不允許出現多個重複的類型

注意:如果結構體裡面有私有屬性也就是小寫定義的字段,則不會被json使用

golang命令行庫Cobra的使用

寫了2次才寫完,內容很長,翻譯了很久,內容來源於Cobra github介紹。翻譯完也更全面的了解了Cobra,功能相當強大完善,各種使用的場景都考慮到了。另外也擴展了一些其它知識,比如 命令行玩法 , Levenshtein distance 等等。以下是正文:

Cobra提供簡單的接口來創建強大的現代化CLI接口,比如git與go工具。Cobra同時也是一個程序, 用於創建CLI程序

Cobra是建立在結構的命令、參數和標誌之上。

命令代表操作,參數和標誌是這些行動的修飾符。

最好的應用程序就像讀取句子。用戶會知道如何使用本機應用程序,因為他們將理解如何使用它。

比如下面的例子, server 是命令, port 是標誌:

在下面的命令,我們告訴Git克隆url地址bare

使用Cobra很簡單。首先,使用 go get 安裝最新版本

然後在你項目里引用Cobra

通常基於Cobra的應用程序將遵循下面的組織結構,當然你也可以遵循自己的接口:

在Cobra應用程序中,通常main.go文件非常空洞。它主要只干一件事:初始化Cobra。

Cobra提供自己的程序來創建你的程序並且添加你想要的命令。這是最簡單的方式把Cobra添加到你的程序里。

這裡 你能找到相關信息

使用Cobra,需要創建一個空的main.go文件和一個rootCmd文件。你可以選擇在合適的地方添加額外的命令。

Cobra不需要特殊的構造函數。簡單的就可以創建你的命令。

理想情況下你把這個放在在 app/cmd/root.go

你會另外定義標誌和處理配置init()函數。

比如 cmd/root.go

你需要在main函數里執行root命令。

通常main.go文件非常空洞。它主要只干一件事:初始化Cobra。

其它的命令通常定義在cmd/目錄下的自己文件內

如果你想創建一個version命令,你可以創建cmd/version.go文件,並在文件里這麼寫:

標誌提供修飾符控制動作命令如何操作

當標誌定義好了,我們需要定義一個變量來關聯標誌

‘持久’表示每個在那個命令下的命令都將能分配到這個標誌。對於全局標誌,’持久’的標誌綁定在root上。

Cobra默認只在目標命令上解析標誌,父命令忽略任何局部標誌。通過打開 Command.TraverseChildren Cobra將會在執行任意目標命令前解析標誌

你同樣可以通過 viper 綁定標誌:

在這個例子中,永久的標記 author 被 viper 綁定, 注意 , 當用戶沒有給 –author 提供值, author 不會被賦值。

標記默認是可選的,如果你希望當一個標記沒有設置時,命令行報錯,你可以標記它為必須的

驗證位置參數可以通過 Command 的 Args 字段。

內置下列驗證方法

一個設置自定義驗證的例子

在下面的例子,我們定義了3個命令。2個在頂級,一個(cmdTimes)是其中一個頂級命令的子命令。在這個例子里,由於沒有給 rootCmd 提供 Run ,單獨的root是不能運行的,必須要有子命令。

我們僅為一個命令定義了標記。

更多關於flags的文檔可以在 找到

更完整大型程序的例子, 可以查看 Hugo .

當你的程序有子命令時,Cobra 會自動給你程序添加help命令。當你運行‘app help’,會調用help命令。另外,help同樣支持其它輸入命令。例如,你有一個沒有任何其它配置的命令叫‘create’,當你調用‘app help create’ Corbra 將會起作用。

下面的輸入是 Cobra 自動生成的。除了命令和標誌的定義,其它不再需要。

help 就跟其它命令一樣,並沒有特殊的邏輯或行為。事實上,你也可以提供你自己help如果你想的話。

你能為默認的命令,提供你自己的help命令或模板。使用下面的方法:

後2個也將適用於任何子命令

當用戶提供無效的標記或命令,Cobra 將會返回 用法 。

你可能從上面的幫助意識到,默認的幫助將被嵌入到用法里然後作為輸出。

你能提供你自己的用法函數或模板給 Cobra 使用。

比如幫助,方法和模板都可以重寫。

如果Version字段設置到了根命令,Cobra 會提供了一個頂層 ‘–version’標記。運行帶上‘–version’標記的程序,將會按照模板版本信息。模板可以通過 cmd.SetVersionTemplate(s string) 方法修改

在命令運行前或運行後,再運行方法非常容易。 PersistentPreRun 和 PreRun 方法將會在 Run 之前執行。 PersistentPostRun 和 PostRun 方法將會在 Run 之後執行。 Persistent*Run 方法會被子命令繼承,如果它們自己沒有定義的話。這些方法將按照下面的屬性執行:

下面的例子,2個命令都使用了上面的特性。當子命令執行的時候,它將執行根命令的 PersistentPreRun ,但不會執行根命令的 PersistentPostRun :

輸出:

Cobra 會自動輸出建議,當遇到“unknown command”錯誤時。這使得當輸入錯誤時, Cobra 的行為類似 git 命令。例如:

建議會基於註冊的子命令自動生成。使用了 Levenshtein distance 的實現。每一個註冊的命令會匹配2個距離(忽略大小寫)來提供建議。

如果你希望在你的命令里,禁用建議或虛弱字符串的距離,使用:

你可以通過 SuggestFor 來給命令提供明確的名詞建議。這個特性允許當字符串不相近,但是意思與你的命令相近,別切你也不想給該命令設置別名。比如:

Cobra 可以基於子命令,標記,等生成文檔。以以下格式:

Cobra 可以生成一個bash-completion文件。如果你給命令添加更多信息,這些completions可以非常強大和靈活。更多介紹在 Bash Completions 。

Golang 遊戲leaf系列(六) Go模塊

在 Golang 遊戲leaf系列(一) 概述與示例 (下文簡稱系列一)中,提到過Go模塊用於創建能夠被 Leaf 管理的 goroutine。Go模塊是對golang中go提供一些額外功能。Go提供回調功能,LinearContext提供順序調用功能。善用 goroutine 能夠充分利用多核資源,Leaf 提供的 Go 機制解決了原生 goroutine 存在的一些問題:

我們來看一個例子(可以在 LeafServer 的模塊的 OnInit 方法中測試):

這裡的 Go 方法接收 2 個函數作為參數,第一個函數會被放置在一個新創建的 goroutine 中執行,在其執行完成之後,第二個函數會在當前 goroutine 中被執行。由此,我們可以看到變量 res 同一時刻總是只被一個 goroutine 訪問,這就避免了同步機制的使用。Go 的設計使得 CPU 得到充分利用,避免操作阻塞當前 goroutine,同時又無需為共享資源同步而憂心。

這裡主動調用了 d.Cb(-d.ChanCb) ,把這個回調取出來了。實際上,在skeleton.Run里會自己取這個通道

看一下源碼:

New方法,會生成指定緩衝長度的ChanCb。然後調用Go方法就是先執行第一個func,然後把第二個放到Cb里。現在手動造一個例子:

這裡解釋一下,d.Go根據源碼來看,實際也是調用了一個協程。然後上面兩次d.Go並不能保證先後順序。目前的輸出結果是1+2那個先執行了,把3寫入d.ChanCb,然後把3讀出來,繼續讀時,d.ChanCb里沒有東西,阻塞了。然後1+1那個協程啟動了,最後又讀到了2。

現在把time.Sleep(time.Second)的注釋解開,會是啥結果呢

這裡執行到time.Sleep睡著了,上面兩個d.Go仍然是不確定順序的,但是會各自的function先執行掉,然後陸續把cb寫入d.ChanCb。看這次輸出,1+2先寫進去的。所以最後執行d.Cb時,就把3先讀出來了。然後d.ChanCb的長度為1,說明還有一個,就是輸出2了。

另外,就是close時會判斷g.pendingGo

這個例子的意思很明顯,NewLinearContext這種方式,即使先調用的慢了半秒,它還是會先執行完。

這裡先是用了一個list,加入的時候用mutexLinearGo鎖了,都加到最後。然後新開協程去處理,讀的時候從最前面開始讀,也要用mutexLinearGo鎖。執行的時候,也要上鎖mutexExecution,確保f()執行完並且寫入g.ChanCb回調,這個mutexExecution鎖才會解除。現在可以改造一個帶回調的例子:

結果說明,確實是2先被寫入了d.ChanCb。

golang 反向代理實例

首先解釋一下反向代理,所謂的反向代理就是代理服務器,充當Web服務器網關的代理服務器。當請求發送到使用反向代理的Web服務器時,他們將先轉到反向代理,由該代理將確定是將其路由到制定的Web服務器。

這個程序是將 本地的8086 端口作為代理服務器,代理上篇 golang HTTP實例 裡面的8090端口

核心只有一個函數 httputil.NewSingleHostReverseProxy

兩個服務同時運行

效果如下:

代理服務器訪問 8086端口時候

訪問原始的端口8090時候

有沒有人用golang實現過restful框架的實例

通過beego快速創建一個Restful風格API項目及API文檔自動化:

Go 語言構建 RESTful Web 服務:

Golang中使用 JWT認證來 保障Restful JSON API的安全(英文):

polaris: 一個用go實現的支持restful的web框架:

關於RESTFUL API 安全認證方式的一些總結:

有沒有人用golang實現過restful框架的實例:

Micro 一個用Go語言實現的微服務框架:

基於微服務庫的可插拔RPC go-micro:

golang適合做web開發嗎?:

a-survey-of-5-go-web-frameworks:

Ozzo Framework:

avelino/awesome-go:

Beego Framework:

golang其實不適合做web開發:

Go語言現有Web開發框架:

使用Golang快速構建WEB應用:

Martini 極好的 Go WEB 框架:

golang 有哪些比較穩定的 web 開發框架?:

golang之context詳解

為什麼需要context

在go服務器中,對於每個請求的request都是在單獨的goroutine中進行的,處理一個request也可能設計多個goroutine之間的交互, 使用context可以使開發者方便的在這些goroutine里傳遞request相關的數據、取消goroutine的signal或截止日期

在並發程序中,由於超時、取消操作或者一些異常情況,往往需要進行搶佔操作或者中斷後續操作。熟悉channel的朋友應該都見過使用done channel來處理此類問題。比如以下這個例子:

上述例子中定義了一個buffer為0的channel done, 子協程運行着定時任務。如果主協程需要在某個時刻發送消息通知子協程中斷任務退出,那麼就可以讓子協程監聽這個done channel,一旦主協程關閉done channel,那麼子協程就可以推出了,這樣就實現了主協程通知子協程的需求。這很好,但是這也是有限的。

如果我們可以在簡單的通知上附加傳遞額外的信息來控制取消:為什麼取消,或者有一個它必須要完成的最終期限,更或者有多個取消選項,我們需要根據額外的信息來判斷選擇執行哪個取消選項。

考慮下面這種情況:假如主協程中有多個任務1, 2, …m,主協程對這些任務有超時控制;而其中任務1又有多個子任務1, 2, …n,任務1對這些子任務也有自己的超時控制,那麼這些子任務既要感知主協程的取消信號,也需要感知任務1的取消信號。

如果還是使用done channel的用法,我們需要定義兩個done channel,子任務們需要同時監聽這兩個done channel。嗯,這樣其實好像也還行哈。但是如果層級更深,如果這些子任務還有子任務,那麼使用done channel的方式將會變得非常繁瑣且混亂。

我們需要一種優雅的方案來實現這樣一種機制:

上層任務取消後,所有的下層任務都會被取消;中間某一層的任務取消後,只會將當前任務的下層任務取消,而不會影響上層的任務以及同級任務。

這個時候context就派上用場了。我們首先看看context的結構設計和實現原理。

context接口

先看Context接口結構,看起來非常簡單。

}

Context接口包含四個方法:

Deadline返回綁定當前context的任務被取消的截止時間;如果沒有設定期限,將返回ok == false。

Done 當綁定當前context的任務被取消時,將返回一個關閉的channel;如果當前context不會被取消,將返回nil。

Err 如果Done返回的channel沒有關閉,將返回nil;如果Done返回的channel已經關閉,將返回非空的值表示任務結束的原因。如果是context被取消,Err將返回Canceled;如果是context超時,Err將返回DeadlineExceeded。

Value 返回context存儲的鍵值對中當前key對應的值,如果沒有對應的key,則返回nil。

可以看到Done方法返回的channel正是用來傳遞結束信號以搶佔並中斷當前任務;Deadline方法指示一段時間後當前goroutine是否會被取消;以及一個Err方法,來解釋goroutine被取消的原因;而Value則用於獲取特定於當前任務樹的額外信息。而context所包含的額外信息鍵值對是如何存儲的呢?其實可以想象一顆樹,樹的每個節點可能攜帶一組鍵值對,如果當前節點上無法找到key所對應的值,就會向上去父節點裡找,直到根節點。

emptyCtx

emptyCtx是一個int類型的變量,但實現了context的接口。emptyCtx沒有超時時間,不能取消,也不能存儲任何額外信息,所以emptyCtx用來作為context樹的根節點。

Background和TODO只是用於不同場景下: Background通常被用於主函數、初始化以及測試中,作為一個頂層的context,也就是說一般我們創建的context都是基於Background;而TODO是在不確定使用什麼context的時候才會使用。

用法 :

原創文章,作者:LISY,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/143240.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
LISY的頭像LISY
上一篇 2024-10-14 18:47
下一篇 2024-10-14 18:47

相關推薦

  • 使用Golang調用Python

    在現代軟件開發中,多種編程語言的協作是相當普遍的。其中一種使用場景是Golang調用Python,這使得在使用Python庫的同時,可以利用Golang的高性能和強大並發能力。這篇…

    編程 2025-04-29
  • Python語法大全解析

    本文旨在全面闡述Python語法,並提供相關代碼示例,幫助讀者更好地理解Python語言。 一、基礎語法 1、Python的注釋方式 # 這是單行注釋 “”” 這是多行注釋,可以注…

    編程 2025-04-29
  • 使用Golang創建黑色背景圖片的方法

    本文將從多個方面介紹使用Golang創建黑色背景圖片的方法。 一、安裝必要的代碼庫和工具 在開始創建黑色背景圖片之前,我們需要先安裝必要的代碼庫和工具: go get -u git…

    編程 2025-04-29
  • Python中複數的語法

    本文將從多個方面對Python中複數的語法進行詳細的闡述。Python中的複數是指具有實部和虛部的數,其中實部和虛部都是浮點數。它們可以用“實數+虛數j”的形式表示。例如,3 + …

    編程 2025-04-29
  • parent.$.dialog是什麼技術的語法

    parent.$.dialog是一種基於jQuery插件的彈出式對話框技術,它提供了一個方便快捷的方式來創建各種類型和樣式的彈出式對話框。它是對於在網站開發中常見的彈窗、提示框等交…

    編程 2025-04-28
  • Python計數循環例子用法介紹

    在這篇文章中,我們將為您提供有關Python計數循環的一些詳細信息,並為您提供示例和代碼,讓您更深入地了解如何使用Python進行計數循環。 一、什麼是計數循環? 計數循環是編程中…

    編程 2025-04-28
  • 編譯原理語法分析思維導圖

    本文將從以下幾個方面詳細闡述編譯原理語法分析思維導圖: 一、語法分析介紹 1.1 語法分析的定義 語法分析是編譯器中將輸入的字符流轉換成抽象語法樹的一個過程。該過程的目的是確保輸入…

    編程 2025-04-27
  • Python進階語法全面解析

    Python語言作為一種廣泛應用於人工智能、數據分析、雲計算等多個領域的編程語言,擁有廣泛的社區和強大的生態系統。Python提供了基本語法以及常用函數和模塊,用於解決大量常規編程…

    編程 2025-04-27
  • LL(1)語法分析器:從語法規則到語法樹

    在編譯原理中,語法分析是編譯器的一個重要階段。語法分析器的作用是將代碼轉換成語法樹,以便後續階段進行處理。LL(1)語法分析器是語法分析器的一種,它採用的是自頂向下的分析方法,可以…

    編程 2025-04-25
  • 深入分析Java Foreach語法

    一、Foreach介紹 Java的Foreach語法是一種迭代語法,被廣泛應用於遍曆數組或集合。其優點是在代碼數量和可讀性方面均佔有優勢,不需要額外定義計數器等變量,便可輕鬆遍歷集…

    編程 2025-04-24

發表回復

登錄後才能評論