《Go語言圣經》函數值、匿名函數遞歸與可變參數

《Go語言圣經》函數值、匿名函數遞歸與可變參數

函數值(Function Values)

在 Go 語言中,函數被視為第一類值(first-class values),這意味著它們可以像其他值一樣被操作:擁有類型、賦值給變量、作為參數傳遞給其他函數或作為返回值。函數值的調用方式與普通函數相同。

func square(n int) int { return n * n }
func negative(n int) int { return -n }
func product(m, n int) int { return m * n }f := square
fmt.Println(f(3)) // 輸出: 9f = negative
fmt.Println(f(3))     // 輸出: -3
fmt.Printf("%T\n", f) // 輸出: func(int) intf = product // 編譯錯誤: 無法將 func(int, int) int 賦值給 func(int) int

函數類型的零值是 nil,調用值為 nil 的函數會導致 panic 錯誤:

var f func(int) int
f(3) // 此處 f 為 nil,會觸發 panic

函數值可以與 nil 比較,但函數值之間不可比較,也不能作為 map 的鍵:

var f func(int) int
if f != nil {f(3)
}

匿名函數遞歸(Recursive Anonymous Functions)

當需要定義遞歸調用的匿名函數時,必須先聲明變量并指定類型,再將匿名函數賦值給該變量。這是因為 Go 編譯器需要在函數體內部解析函數類型。

以下示例展示了如何使用遞歸匿名函數進行拓撲排序(Topological Sort):

// prereqs 記錄了每個課程的前置課程
var prereqs = map[string][]string{"algorithms": {"data structures"},"calculus": {"linear algebra"},"compilers": {"data structures","formal languages","computer organization",},"data structures":       {"discrete math"},"databases":             {"data structures"},"discrete math":         {"intro to programming"},"formal languages":      {"discrete math"},"networks":              {"operating systems"},"operating systems":     {"data structures", "computer organization"},"programming languages": {"data structures", "computer organization"},
}func main() {for i, course := range topoSort(prereqs) {fmt.Printf("%d:\t%s\n", i+1, course)}
}func topoSort(m map[string][]string) []string {var order []stringseen := make(map[string]bool)// 聲明遞歸函數類型var visitAll func(items []string)// 賦值匿名函數visitAll = func(items []string) {for _, item := range items {if !seen[item] {seen[item] = truevisitAll(m[item]) // 遞歸調用order = append(order, item)}}}var keys []stringfor key := range m {keys = append(keys, key)}sort.Strings(keys)visitAll(keys)return order
}

關鍵點

  1. 必須先聲明 visitAll 變量并指定類型 func(items []string)
  2. 再將匿名函數賦值給 visitAll
  3. 函數體內部可正確解析 visitAll 的類型

可變參數(Variadic Functions)

可變參數函數可以接收任意數量的指定類型參數,在參數列表最后一個類型前加 ... 表示:

func sum(vals ...int) int {total := 0for _, val := range vals {total += val}return total
}fmt.Println(sum())           // 輸出: 0
fmt.Println(sum(3))          // 輸出: 3
fmt.Println(sum(1, 2, 3, 4)) // 輸出: 10

在函數體內部,可變參數被視為切片類型(如 []int)。若要傳遞現有切片給可變參數函數,需在切片后加 ...

values := []int{1, 2, 3, 4}
fmt.Println(sum(values...)) // 輸出: 10

可變參數函數與以切片為參數的函數類型不同:

func f(...int) {}
func g([]int) {}fmt.Printf("%T\n", f) // 輸出: func(...int)
fmt.Printf("%T\n", g) // 輸出: func([]int)

可變參數函數常用于格式化字符串,例如:

func errorf(linenum int, format string, args ...interface{}) {fmt.Fprintf(os.Stderr, "Line %d: ", linenum)fmt.Fprintf(os.Stderr, format, args...)fmt.Fprintln(os.Stderr)
}linenum, name := 12, "count"
errorf(linenum, "undefined: %s", name) // 輸出: Line 12: undefined: count

其中 interface{} 表示最后一個參數可接收任意類型。

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

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

相關文章

vtk和opencv和opengl直接的區別是什么?

簡介 VTK、OpenCV 和 OpenGL 是三個在計算機圖形學、圖像處理和可視化領域廣泛使用的工具庫,但它們在功能、應用場景和底層技術上存在顯著差異。以下是它們的核心區別和特點對比: 1. 核心功能與定位 工具核心功能主要應用領域VTK (Visualization Toolk…

最新豆包大模型發布!火山引擎推出Agent開發新范式

Datawhale大會 2025火山引擎 Force 原動力大會 6月11日-12日,北京國家會議中心人山人海,2025 火山引擎 Force 原動力大會如約而至。 作為開發者社區的一員,這場大會上的一系列新發布讓我們感受到了:這個 Agent 技術落地元年的關鍵…

RFC4291-IPv6地址架構解說

RFC 4291 是由互聯網工程任務組(IETF)發布的關于 IPv6 地址架構 的標準文檔。 該文檔詳細定義了 IPv6 地址的格式、類型、表示方法以及分配方式。 以下是對 RFC 4291 中 IPv6 地址架構的全面解析,包括地址格式、類型、表示方法、特殊地址以…

簡單對比 **HTTP**、**MQTT** 和 **CoAP** 這三種通信協議

對比 HTTP、MQTT 和 CoAP 這三種通信協議,從 消息結構、資源占用、安全性 等方面進行全面分析。 🌐 HTTP vs MQTT vs CoAP 對比 特性HTTPMQTTCoAP協議層級應用層基于 TCP應用層基于 TCP / WebSocket應用層基于 UDP (也支持 TCP)消息模式請求/響應 (客戶…

【Dify 案例】【自然語言轉SQL案例】【五】【實戰二】【財務管理查詢商品信息數據】

援引實戰一,進行數據業務處理化 1.開始 2.自然語言轉SQL的工具 3.參數提取器 4.SQL查詢

FPGA基礎 -- Verilog語言要素之標識符

一、什么是標識符(Identifier) 在 Verilog 中,標識符是用戶定義的名字,用于標識模塊、變量、端口、函數、任務、參數、宏定義等各種語言要素。 就像 C 語言的變量名、函數名一樣,Verilog 中的標識符為 HDL 代碼提供了…

Tomcat雙擊startup.bat閃退的解決方法

首先需要確認java環境是否配置正確,jdk是否安裝正確 winR打開cmd,輸入該命令 java -version 出現對應的版本就說明jdk配置正確 如果沒有,則參考jdk的安裝及配置 如果以上都沒有問題,就繼續排查 確認Tomcat的環境變量配置 概…

計算機基礎(三):深入解析Java中的原碼、反碼、補碼

計算機基礎系列文章 計算機基礎(一):ASCll、GB2312、GBK、Unicode、UTF-32、UTF-16、UTF-8深度解析 計算機基礎(二):輕松理解二進制、八進制、十進制和十六進制 計算機基礎(三):深入解析Java中的原碼、反碼、補碼 目錄 引言一、 基礎概念&…

phpstudy無法啟動mysql,一啟動就關閉,完美解決

phpstudy無法啟動mysql,一啟動就關閉,完美解決 phpstudy的mysql無法啟動,一啟動就關閉如何解決。 問題出現的原因:phpstudy自帶的mysql,可能與之前單獨安裝的mysql發生沖突。(之前安裝的mysql已經占用3306端口) 解決方…

mysql中的<>和!=

在MySQL中&#xff0c;<> 運算符表示 不等于。它與 ! 運算符功能完全相同&#xff0c;都是用于比較兩個表達式是否不相等。 SELECT * FROM table_name WHERE column_name <> value;當 column_name 的值不等于 value 時&#xff0c;返回該行當值相等或為 NULL 時&a…

C#學習日記

命名空間 知識點一 命名空間基本概念 概念 命名空間是用來組織和重用代碼的 作用 就像是一個工具包&#xff0c;類就像是一件一件的工具&#xff0c;都是申明在命名空間中的 知識點二 命名空間的使用 基本語法 namespace 命名空間名 {類類 } namespace MyGame {class GameO…

第八十二篇 大數據開發基礎:樹形數據結構深度解析與實戰指南(附創新生活案例)

目錄 一、樹的本質&#xff1a;層次化數據組織二、生活中的樹形智慧&#xff1a;無處不在的層次案例1&#xff1a;圖書館圖書分類系統案例2&#xff1a;電商平臺商品類目樹案例3&#xff1a;城市行政區域劃分 三、大數據中的核心樹結構1. B樹&#xff1a;數據庫索引的脊梁2. 決…

從0開始學計算機視覺--Day1--計算機視覺的起源

我們經常能聽到計算機視覺這個詞語&#xff0c;像數字圖像處理&#xff0c;算法設計&#xff0c;深度學習等領域。但很少有人會先去了解清楚這門知識&#xff0c;而是用到什么再學什么&#xff0c;雖然這在項目進度上能節省不少時間&#xff0c;但有時候囫圇吞棗式地學習容易落…

簡單的 ?Flask? 后端應用

from flask import Flask, request, jsonify, session import os app Flask(__name__) app.secret_key os.urandom(24) users { 123: admin, admin: admin } # 登錄接口 app.route(/login, methods[POST]) def login(): data request.get_json() username data.get(usern…

spring-webmvc @PathVariable 典型用法

典型用法 基礎用法 GetMapping("/users/{id}") public String getUser(PathVariable Long id) {return "User ID: " id; } 請求&#xff1a;/users/1001 輸出&#xff1a;User ID: 1001---- GetMapping("/users/{userId}/orders/{orderId}") …

LVS+Keepliaved高可用群集

目錄 keepalived雙擊熱備基礎知識1.keepallived概述及安裝keepalived的熱備方式 2.使用keepalived實現雙機熱備 案例1.基礎主備調度器環境配置2.配置主調度器3.配置從調度器4.配置兩臺節點服務器5.測試 keepalived雙擊熱備基礎知識 Keepalived 起初是專門針對 LVS 設計的一款強…

在Unreal Engine 5(UE5)中,Get PlayerPawn和Get PlayerController的區別以及如何計算玩家和目標之間的距離。

一、兩者區別 在Unreal Engine 5&#xff08;UE5&#xff09;中&#xff0c;獲取玩家的位置信息通常有兩種方式&#xff1a;通過PlayerPawn或通過PlayerController。具體使用哪一個取決于你想要獲取的是哪個實體的位置。 1.Get Player Pawn&#xff1a; PlayerPawn是玩家實際…

linux線程同步

互斥鎖 同步與互斥概述** 現代操作系統基本都是多任務操作系統&#xff0c;即同時有大量可調度實體在運行。在多任務操作系統中&#xff0c;同時運行的多個任務可能&#xff1a; 都需要訪問/使用同一種資源 多個任務之間有依賴關系&#xff0c;某個任務的運行依賴于另一個任…

Spring 的IoC 和 AOP

第一部分&#xff1a;關于 IoC (控制反轉) 1. 核心思想 (What & Why) 首先&#xff0c;我會先解釋 IoC 的核心思想&#xff0c;而不是直接講技術。 “IoC&#xff0c;即控制反轉&#xff0c;它是一種重要的設計思想&#xff0c;而不是一個具體的技術。它的核心是將傳統上…

[實戰] Windows 文件讀寫函數 `ReadFile()` 和 `WriteFile()` 的阻塞與非阻塞操作詳解(含完整C語言示例)

Windows 文件讀寫函數 ReadFile() 和 WriteFile() 的阻塞與非阻塞操作詳解&#xff08;含完整C語言示例&#xff09; 在 Windows 平臺進行文件或設備&#xff08;如串口、管道&#xff09;編程時&#xff0c;ReadFile() 和 WriteFile() 是最常用的兩個 API 函數。它們既可以以…