化整為零優化重用,Go lang1.18入門精煉教程,由白丁入鴻儒,go lang函數的定義和使用EP07

来源:https://www.cnblogs.com/v3ucn/archive/2022/08/11/16576833.html
-Advertisement-
Play Games

函數是基於功能或者邏輯進行聚合的可復用的代碼塊。將一些複雜的、冗長的代碼抽離封裝成多個代碼片段,即函數,有助於提高代碼邏輯的可讀性和可維護性。不同於Python,由於 Go lang是編譯型語言,編譯之後再運行,所以函數的定義順序無關痛癢。 函數聲明 在 Go lang里,函數聲明語法如下: fun ...


函數是基於功能或者邏輯進行聚合的可復用的代碼塊。將一些複雜的、冗長的代碼抽離封裝成多個代碼片段,即函數,有助於提高代碼邏輯的可讀性和可維護性。不同於Python,由於 Go lang是編譯型語言,編譯之後再運行,所以函數的定義順序無關痛癢。

函數聲明

在 Go lang里,函數聲明語法如下:

func function_name(parameter_list) (result_list) {  
    //函數邏輯  
}

這裡使用function的簡寫形式 func關鍵詞,後面依次接 function_name(函數名) , parameter_list(參數列表) , result_list(返回值列表)以及函數體 。

parameter_list(參數列表)成員:函數的參數名以及參數類型,這些參數作為局部變數,其值由參數調用者提供,函數中的參數列表和返回值並非是必須的。

result_list(返回值列表):函數返回值的變數名以及類型,如果函數返回一個無名變數或者沒有返回值,返回值列表的括弧是可以省略的。

如果有連續若幹個參數的類型一致,那麼只需在最後一個參數後添加該類型:

package main  
  
import "fmt"  
  
// 函數返回一個無名變數,返回值列表的括弧省略  
func sum(x int, y int) int {  
	return x + y  
}  
  
// 無參數列表和返回值  
func printBookName() {  
	fmt.Println("go lang1.18")  
}  
  
// 參數的類型一致,只在最後一個參數後添加該類型  
func sub(x, y int) int {  
	return x - y  
}  
  
func main() {  
	fmt.Println("1 + 1 = ", sum(1, 1))  
	printBookName()  
	fmt.Println("2 - 1 =", sub(2, 1))  
}

程式返回:

command-line-arguments  
1 + 1 =  2  
go lang1.18  
2 - 1 = 1

不定長參數

和Python一樣,Go lang也支持不定長參數,即參數有多少個並不確定的情況。

在參數類型前面加 ... 表示一個切片,用來接收調用者傳入的參數。註意,如果該函數下有其他類型的參數,這些其他參數必須放在參數列表的前面,切片必須放在最後:

package main  
  
import "fmt"  
  
func show(args ...string) int {  
	sum := 0  
	for _, item := range args {  
		fmt.Println(item)  
		sum += 1  
	}  
	return sum  
}  
  
func main() {  
	fmt.Println(show("1", "2", "3"))  
}

和Python的*args用法差不多,但需要註意必須要聲明函數的數據類型,程式返回:

1  
2  
3  
3

如果傳多個參數的數據類型都不一樣,可以指定類型為 ...interface{} ,然後再進行遍歷:

package main  
  
import "fmt"  
  
func PrintType(args ...interface{}) {  
	for _, arg := range args {  
		switch arg.(type) {  
		case int:  
			fmt.Println(arg, "type is int.")  
		case string:  
			fmt.Println(arg, "type is string.")  
		case float64:  
			fmt.Println(arg, "type is float64.")  
		default:  
			fmt.Println(arg, "is an unknown type.")  
		}  
	}  
}  
  
func main() {  
	PrintType(1, 3.1415, "go lang 1.18")  
}

此外,還可以使用 ... 可以用來解序列,能將函數的可變參數(即切片)一個一個取出來,傳遞給另一個可變參數的函數,而不是傳遞可變參數變數本身:

package main  
  
import "fmt"  
  
func main() {  
	var s []string  
	s = append(s, []string{"1", "2", "3"}...)  
	fmt.Println(s)  
}

這裡將字元串切片取出來後,傳遞給內置的append方法,程式返回:

[1 2 3]

函數的返回值

一個函數可以沒有返回值,也可以有一個返回值,也可以有返回多個值:

package main  
  
import "fmt"  
  
func swap(x, y string) (string, string) {  
	return y, x  
}  
  
func SumAndProduct(A, B int) (add int, Multiplied int) {  
	add = A + B  
	Multiplied = A * B  
	return  
}  
  
func main() {  
	a, b := swap("Mahesh", "Kumar")  
	fmt.Println(a, b)  
  
	fmt.Println(SumAndProduct(1, 2))  
  
}

程式返回:

Kumar Mahesh  
3 2

_ 是Go lang里的空白標識符。它可以代替任何類型的任何值。我們可以利用它來忽略某些別人會用到但我們不會用到的函數返回值:

package main  
  
import (  
	"fmt"  
)  
  
func rectProps(length, width float64) (float64, float64) {  
	var area = length * width  
	var perimeter = (length + width) * 2  
	return area, perimeter  
}  
func main() {  
	area, _ := rectProps(10.8, 5.6) // perimeter is discarded  
	fmt.Printf("Area %f ", area)  
}

程式返回:

Area 60.480000

匿名函數

有點類似Python中的lambda表達式,但實際上並不是作為語法糖而存在:

package main  
  
import (  
	"fmt"  
)  
  
func main() {  
	f := func() {  
		fmt.Println("hello world")  
	}  
	f()                   //hello world  
	fmt.Printf("%T\n", f) //列印 func()  
}

程式返回:

hello world  
func()

一望而知,只是匿名而已,但通過變數可調用,另外也可以擁有參數:

package main  
  
import (  
   "fmt"  
)  
func main() {  
   f:=func(args string){  
      fmt.Println(args)  
   }  
   f("hello world")//hello world  
   //或  
   (func(args string){  
        fmt.Println(args)  
    })("hello world")//hello world  
    //或  
    func(args string) {  
        fmt.Println(args)  
    }("hello world") //hello world  
}

程式返回:

hello world  
hello world  
hello world

基本上,匿名函數和命名函數用法上並無二致。

閉包(closure)

很多語言都有閉包的概念,簡單理解就是函數的嵌套:

package main  
  
import "fmt"  
  
func main() {  
    a := Fun()  
    b:=a("hello ")  
    c:=a("hello ")  
    fmt.Println(b)//worldhello   
    fmt.Println(c)//worldhello hello   
}  
func Fun() func(string) string {  
    a := "world"  
    return func(args string) string {  
        a += args  
        return  a  
    }  
}

程式返回:

worldhello   
worldhello hello

這裡我們將方法作為參數傳遞到方法內部執行,這樣內層的函數可以使用外層函數的所有變數,即使外層函數已經執行完畢。

延遲函數

延遲其實是延遲(defer)語句,延遲語句被用於執行一個函數調用,在這個函數之前,延遲語句返回:

package main  
  
import "fmt"  
  
func main() {  
	a := 1  
	b := 2  
	defer fmt.Println(b)  
	fmt.Println(a)  
}

程式返回:

1  
2

說白了就是一種倒裝的形式,非延遲語句先執行,最後再執行延遲語句。

延遲也並不僅僅局限於函數內部語句,延遲一個方法調用也是可以的:

package main  
  
import (  
	"fmt"  
)  
  
type person struct {  
	firstName string  
	lastName  string  
}  
  
func (p person) fullName() {  
	fmt.Printf("%s %s", p.firstName, p.lastName)  
}  
  
func main() {  
	p := person{  
		firstName: "go lang",  
		lastName:  "python",  
	}  
	defer p.fullName()  
	fmt.Printf("Welcome ")  
}

程式返回:

Welcome go lang python

初始化函數

顧名思義,和Python中的魔法方法init一樣,可以提前做一些初始化操作:

package main  
  
import "fmt"  
  
var a int = initVar()  
  
func init() {  
	fmt.Println("init2")  
}  
  
func init() {  
	fmt.Println("init")  
}  
  
func initVar() int {  
	fmt.Println("init var...")  
	return 100  
}  
  
func main() {  
	fmt.Println("main...")  
}

程式返回:

init var...  
init2  
init 

這裡的初始化順序是:變數初始化->init()->main()

和Python不同的是,每個包可以有多個初始化函數。

結語

歸根結底,函數可以被認為是Go lang中的一種數據類型,可以作為另一個函數的參數,也可以作為另一個函數的返回值,使用起來相當靈活,但我們也不能矯枉過正,毫無節制地用函數封裝邏輯,造成過度封裝的現象。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 關於Teamind Teamind 是新一代的遠程互動會議平臺。基於 Teamind 無限延伸、任意縮放的線上白板上,每一個參與者都可以利用便簽、圖形、手繪、圖片等各種各樣的元素進行創作,而主持人可以使用計時器、目錄、演講、投票等功能引導一場順暢而高效的會議。 Teamind 就像是一個「虛擬會議室 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • Java集合02 6.ArrayList ArrayList的註意事項: Permits all element , including null ,ArrayList 可以加入null ,並且可以加入多個 ArrayList是由數組來實現數據存儲的 ArrayList基本等同於Vector,除了A ...
  • 歡迎大家移步 我的博客 查看原文。 1. 前言 上機時遇到如下 C++ 代碼 ( C 代碼): //刪除帶頭結點的多項式單鏈表中繫數為 0 項 void DelZero(PolyNode *&L) { PolyNode *pre = L, *p = pre->next; while (p != NU ...
  • 基本類型 Rust 每個值都有其確切的數據類型,總的來說可以分為兩類:基本類型和複合類型。 基本類型意味著它們往往是一個最小化原子類型,無法解構為其它類型(一般意義上來說),由以下組成: 數值類型: 有符號整數 (i8, i16, i32, i64, isize)、 無符號整數 (u8, u16,  ...
  • ##網路協議 通過電腦網路可以使多台電腦實現連接,位於同一個網路中的電腦在進行連接和通信時需要遵守一定的規則,這就好比在道路中行駛的汽車一定要遵守交通規則一樣。在電腦網路中,這些連接和通信的規則被稱為網路通信協議,它對數據的傳輸格式、傳輸速率、傳輸步驟等做了統一規定,通信雙方必須同時遵守才能 ...
  • 《笨辦法學Python3 》免費下載地址 內容簡介 · · · · · · 本書是一本Python入門書籍,適合對電腦瞭解不多,沒有學過編程,但對編程感興趣的讀者學習使用。這本書以習題的方式引導讀者一步一步學習編程,從簡單的列印一直講到完整項目的實現,讓初學者從基礎的編程技術入手,最終體驗到軟體開 ...
  • 啥是函數式介面、它和JAVA中普通的介面有啥區別?函數式介面有啥用?如何在實際編碼中使用函數式介面?帶著這些問題,我們一起來認識下函數式介面的廬山真面目。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...